aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/transport/chttp2/timeout_encoding.c15
-rw-r--r--test/core/transport/chttp2/timeout_encoding_test.c8
2 files changed, 17 insertions, 6 deletions
diff --git a/src/core/transport/chttp2/timeout_encoding.c b/src/core/transport/chttp2/timeout_encoding.c
index 8cbf987a42..06ce277ffe 100644
--- a/src/core/transport/chttp2/timeout_encoding.c
+++ b/src/core/transport/chttp2/timeout_encoding.c
@@ -137,7 +137,7 @@ static int is_all_whitespace(const char *p) {
}
int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout) {
- uint32_t x = 0;
+ int32_t x = 0;
const uint8_t *p = (const uint8_t *)buffer;
int have_digit = 0;
/* skip whitespace */
@@ -145,13 +145,16 @@ int grpc_chttp2_decode_timeout(const char *buffer, gpr_timespec *timeout) {
;
/* decode numeric part */
for (; *p >= '0' && *p <= '9'; p++) {
- uint32_t xp = x * 10u + (uint32_t)*p - (uint32_t)'0';
+ int32_t digit = (int32_t)(*p - (uint8_t)'0');
have_digit = 1;
- if (xp < x) {
- *timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
- return 1;
+ /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */
+ if (x >= (100 * 1000 * 1000)) {
+ if (x != (100 * 1000 * 1000) || digit != 0) {
+ *timeout = gpr_inf_future(GPR_CLOCK_REALTIME);
+ return 1;
+ }
}
- x = xp;
+ x = x * 10 + digit;
}
if (!have_digit) return 0;
/* skip whitespace */
diff --git a/test/core/transport/chttp2/timeout_encoding_test.c b/test/core/transport/chttp2/timeout_encoding_test.c
index ba6c3191f1..ec1260419f 100644
--- a/test/core/transport/chttp2/timeout_encoding_test.c
+++ b/test/core/transport/chttp2/timeout_encoding_test.c
@@ -126,8 +126,16 @@ void test_decoding(void) {
decode_suite('S', gpr_time_from_seconds);
decode_suite('M', gpr_time_from_minutes);
decode_suite('H', gpr_time_from_hours);
+ assert_decodes_as("1000000000S",
+ gpr_time_from_seconds(1000 * 1000 * 1000, GPR_TIMESPAN));
assert_decodes_as("1000000000000000000000u",
gpr_inf_future(GPR_CLOCK_REALTIME));
+ assert_decodes_as("1000000001S",
+ gpr_inf_future(GPR_CLOCK_REALTIME));
+ assert_decodes_as("2000000001S",
+ gpr_inf_future(GPR_CLOCK_REALTIME));
+ assert_decodes_as("9999999999S",
+ gpr_inf_future(GPR_CLOCK_REALTIME));
}
void test_decoding_fails(void) {