From 6633647822c8dff848a7a49bd6db974485f884bd Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Tue, 19 Jan 2016 17:55:40 -0800 Subject: [PATCH] improve decode_timeout implementation --- src/core/transport/chttp2/timeout_encoding.c | 15 +++++++++------ .../core/transport/chttp2/timeout_encoding_test.c | 8 ++++++++ 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 8cbf987a425..06ce277ffe9 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 ba6c3191f1e..ec1260419f0 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) {