aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-12-12 11:23:25 -0800
committerPaul Eggert2013-12-12 11:23:25 -0800
commit4618713ae48aac51c6f1a2474cc981f32c2bbede (patch)
tree11ede5202ee196ab2fb658a6c5a4bcffc4dc413b /src
parent01633a17e74e638f31ec71c3587481f0084574f2 (diff)
downloademacs-4618713ae48aac51c6f1a2474cc981f32c2bbede.tar.gz
emacs-4618713ae48aac51c6f1a2474cc981f32c2bbede.zip
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')
-rw-r--r--src/ChangeLog8
-rw-r--r--src/regex.c20
2 files changed, 17 insertions, 11 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 839630e93ea..7bbcb345a0f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
12013-12-12 Paul Eggert <eggert@cs.ucla.edu>
2
3 Avoid undefined behavior with huge regexp interval counts.
4 * regex.c (GET_INTERVAL_COUNT): Rename from 'GET_UNSIGNED_NUMBER',
5 since it's now specialized to interval counts. All uses changed.
6 Do not assume wrapraound on signed integer overflow.
7 (regex_compile): Simplify based on the above changes.
8
12013-12-12 Eli Zaretskii <eliz@gnu.org> 92013-12-12 Eli Zaretskii <eliz@gnu.org>
2 10
3 Support file names on MS-Windows that use characters outside of 11 Support file names on MS-Windows that use characters outside of
diff --git a/src/regex.c b/src/regex.c
index b45dbcaada7..faa645cdd28 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -1989,7 +1989,7 @@ struct range_table_work_area
1989#endif /* emacs */ 1989#endif /* emacs */
1990 1990
1991/* Get the next unsigned number in the uncompiled pattern. */ 1991/* Get the next unsigned number in the uncompiled pattern. */
1992#define GET_UNSIGNED_NUMBER(num) \ 1992#define GET_INTERVAL_COUNT(num) \
1993 do { \ 1993 do { \
1994 if (p == pend) \ 1994 if (p == pend) \
1995 FREE_STACK_RETURN (REG_EBRACE); \ 1995 FREE_STACK_RETURN (REG_EBRACE); \
@@ -1998,13 +1998,11 @@ struct range_table_work_area
1998 PATFETCH (c); \ 1998 PATFETCH (c); \
1999 while ('0' <= c && c <= '9') \ 1999 while ('0' <= c && c <= '9') \
2000 { \ 2000 { \
2001 int prev; \
2002 if (num < 0) \ 2001 if (num < 0) \
2003 num = 0; \ 2002 num = 0; \
2004 prev = num; \ 2003 if (RE_DUP_MAX / 10 - (RE_DUP_MAX % 10 < c - '0') < num) \
2005 num = num * 10 + c - '0'; \
2006 if (num / 10 != prev) \
2007 FREE_STACK_RETURN (REG_BADBR); \ 2004 FREE_STACK_RETURN (REG_BADBR); \
2005 num = num * 10 + c - '0'; \
2008 if (p == pend) \ 2006 if (p == pend) \
2009 FREE_STACK_RETURN (REG_EBRACE); \ 2007 FREE_STACK_RETURN (REG_EBRACE); \
2010 PATFETCH (c); \ 2008 PATFETCH (c); \
@@ -3310,18 +3308,18 @@ regex_compile (const_re_char *pattern, size_t size, reg_syntax_t syntax,
3310 3308
3311 beg_interval = p; 3309 beg_interval = p;
3312 3310
3313 GET_UNSIGNED_NUMBER (lower_bound); 3311 GET_INTERVAL_COUNT (lower_bound);
3314 3312
3315 if (c == ',') 3313 if (c == ',')
3316 GET_UNSIGNED_NUMBER (upper_bound); 3314 {
3315 GET_INTERVAL_COUNT (upper_bound);
3316 if (upper_bound < lower_bound)
3317 FREE_STACK_RETURN (REG_BADBR);
3318 }
3317 else 3319 else
3318 /* Interval such as `{1}' => match exactly once. */ 3320 /* Interval such as `{1}' => match exactly once. */
3319 upper_bound = lower_bound; 3321 upper_bound = lower_bound;
3320 3322
3321 if (lower_bound < 0 || upper_bound > RE_DUP_MAX
3322 || (upper_bound >= 0 && lower_bound > upper_bound))
3323 FREE_STACK_RETURN (REG_BADBR);
3324
3325 if (!(syntax & RE_NO_BK_BRACES)) 3323 if (!(syntax & RE_NO_BK_BRACES))
3326 { 3324 {
3327 if (c != '\\') 3325 if (c != '\\')