diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2013-12-12 11:23:25 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2013-12-12 11:23:25 -0800 |
commit | 4618713ae48aac51c6f1a2474cc981f32c2bbede (patch) | |
tree | 11ede5202ee196ab2fb658a6c5a4bcffc4dc413b /src/regex.c | |
parent | 01633a17e74e638f31ec71c3587481f0084574f2 (diff) |
Avoid undefined behavior with huge regexp interval counts.
* regex.c (GET_INTERVAL_COUNT): Rename from 'GET_UNSIGNED_NUMBER',
since it's now specialized to interval counts. All uses changed.
Do not assume wrapraound on signed integer overflow.
(regex_compile): Simplify based on the above changes.
Diffstat (limited to 'src/regex.c')
-rw-r--r-- | src/regex.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/src/regex.c b/src/regex.c index b45dbcaada..faa645cdd2 100644 --- a/src/regex.c +++ b/src/regex.c @@ -1989,7 +1989,7 @@ struct range_table_work_area #endif /* emacs */ /* Get the next unsigned number in the uncompiled pattern. */ -#define GET_UNSIGNED_NUMBER(num) \ +#define GET_INTERVAL_COUNT(num) \ do { \ if (p == pend) \ FREE_STACK_RETURN (REG_EBRACE); \ @@ -1998,13 +1998,11 @@ struct range_table_work_area PATFETCH (c); \ while ('0' <= c && c <= '9') \ { \ - int prev; \ if (num < 0) \ num = 0; \ - prev = num; \ - num = num * 10 + c - '0'; \ - if (num / 10 != prev) \ + if (RE_DUP_MAX / 10 - (RE_DUP_MAX % 10 < c - '0') < num) \ FREE_STACK_RETURN (REG_BADBR); \ + num = num * 10 + c - '0'; \ if (p == pend) \ FREE_STACK_RETURN (REG_EBRACE); \ PATFETCH (c); \ @@ -3310,18 +3308,18 @@ regex_compile (const_re_char *pattern, size_t size, reg_syntax_t syntax, beg_interval = p; - GET_UNSIGNED_NUMBER (lower_bound); + GET_INTERVAL_COUNT (lower_bound); if (c == ',') - GET_UNSIGNED_NUMBER (upper_bound); + { + GET_INTERVAL_COUNT (upper_bound); + if (upper_bound < lower_bound) + FREE_STACK_RETURN (REG_BADBR); + } else /* Interval such as `{1}' => match exactly once. */ upper_bound = lower_bound; - if (lower_bound < 0 || upper_bound > RE_DUP_MAX - || (upper_bound >= 0 && lower_bound > upper_bound)) - FREE_STACK_RETURN (REG_BADBR); - if (!(syntax & RE_NO_BK_BRACES)) { if (c != '\\') |