summaryrefslogtreecommitdiff
path: root/src/regex.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2013-12-12 11:23:25 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2013-12-12 11:23:25 -0800
commit4618713ae48aac51c6f1a2474cc981f32c2bbede (patch)
tree11ede5202ee196ab2fb658a6c5a4bcffc4dc413b /src/regex.c
parent01633a17e74e638f31ec71c3587481f0084574f2 (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.c20
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 != '\\')