From f4dd24c80067ff4b601d58f43797f28bf56f6b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 26 Apr 2024 13:07:52 +0200 Subject: [PATCH] Avoid undefined behavior when parsing bounds. Signed integer overflow is undefined behavior, so use unsigned long internally while parsing numbers, and substitute INT_MAX at the end if overflow occurred. --- lib/tre-parse.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/tre-parse.c b/lib/tre-parse.c index dccd6e6..5b9b615 100644 --- a/lib/tre-parse.c +++ b/lib/tre-parse.c @@ -576,22 +576,35 @@ tre_parse_bracket(tre_parse_ctx_t *ctx, tre_ast_node_t **result) } -/* Parses a positive decimal integer. Returns -1 if the string does not - contain a valid number. */ +/* Parses a positive decimal integer capped at INT_MAX. Returns -1 if the + string does not contain a valid number. */ static int tre_parse_int(const tre_char_t **regex, const tre_char_t *regex_end) { - int num = -1; + unsigned long num = 0; + int overflow = 0; const tre_char_t *r = *regex; while (r < regex_end && *r >= L'0' && *r <= L'9') { - if (num < 0) - num = 0; - num = num * 10 + *r - L'0'; + if (!overflow) + { + if (num * 10 + *r - L'0' < num) + { + overflow = 1; + } + else + { + num = num * 10 + *r - L'0'; + if (num > INT_MAX) + overflow = 1; + } + } r++; } + if (r == *regex) + return -1; *regex = r; - return num; + return overflow ? INT_MAX : (int)num; }