Changeset 31388 in webkit


Ignore:
Timestamp:
Mar 27, 2008, 11:41:17 PM (17 years ago)
Author:
mrowe@apple.com
Message:

2008-03-27 Darin Adler <Darin Adler>

Reviewed by Mark Rowe.

<rdar://problem/5826236> Regular expressions with large nested repetition counts can have their
compiled length calculated incorrectly.

  • pcre/pcre_compile.cpp: (multiplyWithOverflowCheck): (calculateCompiledPatternLength): Check for overflow when dealing with nested repetition counts and bail with an error rather than returning incorrect results.

2008-03-27 Mark Rowe <mrowe@apple.com>

Reviewed by Adam Roben.

Tests for <rdar://problem/5826236> Regular expressions with large nested repetition counts can have their
compiled length calculated incorrectly.

  • fast/js/regexp-overflow-expected.txt:
  • fast/js/resources/regexp-overflow.js:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r31353 r31388  
     12008-03-27  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Mark Rowe.
     4
     5        <rdar://problem/5826236> Regular expressions with large nested repetition counts can have their
     6        compiled length calculated incorrectly.
     7
     8        * pcre/pcre_compile.cpp:
     9        (multiplyWithOverflowCheck):
     10        (calculateCompiledPatternLength): Check for overflow when dealing with nested repetition counts
     11        and bail with an error rather than returning incorrect results.
     12
    1132008-03-26  Mark Rowe  <mrowe@apple.com>
    214
  • trunk/JavaScriptCore/pcre/pcre_compile.cpp

    r29110 r31388  
    19861986}
    19871987
     1988static inline int multiplyWithOverflowCheck(int a, int b)
     1989{
     1990    if (!a || !b)
     1991        return 0;
     1992    if (a > MAX_PATTERN_SIZE / b)
     1993        return -1;
     1994    return a * b;
     1995}
     1996
    19881997static int calculateCompiledPatternLength(const UChar* pattern, int patternLength, JSRegExpIgnoreCaseOption ignoreCase,
    19891998    CompileData& cd, ErrorCode& errorcode)
     
    19922001     amount of store required to hold the compiled code. This does not have to be
    19932002     perfect as long as errors are overestimates. */
    1994    
     2003
     2004    if (patternLength > MAX_PATTERN_SIZE) {
     2005        errorcode = ERR16;
     2006        return -1;
     2007    }
     2008
    19952009    int length = 1 + LINK_SIZE;      /* For initial BRA plus length */
    19962010    int branch_extra = 0;
     
    24142428                 bracket set. */
    24152429               
     2430                int repeatsLength;
    24162431                if (minRepeats == 0) {
    24172432                    length++;
    2418                     if (maxRepeats > 0) length += (maxRepeats - 1) * (duplength + 3 + 2 * LINK_SIZE);
     2433                    if (maxRepeats > 0) {
     2434                        repeatsLength = multiplyWithOverflowCheck(maxRepeats - 1, duplength + 3 + 2 * LINK_SIZE);
     2435                        if (repeatsLength < 0) {
     2436                            errorcode = ERR16;
     2437                            return -1;
     2438                        }
     2439                        length += repeatsLength;
     2440                        if (length > MAX_PATTERN_SIZE) {
     2441                            errorcode = ERR16;
     2442                            return -1;
     2443                        }
     2444                    }
    24192445                }
    24202446               
     
    24262452               
    24272453                else {
    2428                     length += (minRepeats - 1) * duplength;
    2429                     if (maxRepeats > minRepeats)   /* Need this test as maxRepeats=-1 means no limit */
    2430                         length += (maxRepeats - minRepeats) * (duplength + 3 + 2 * LINK_SIZE)
    2431                         - (2 + 2 * LINK_SIZE);
     2454                    repeatsLength = multiplyWithOverflowCheck(minRepeats - 1, duplength);
     2455                    if (repeatsLength < 0) {
     2456                        errorcode = ERR16;
     2457                        return -1;
     2458                    }
     2459                    length += repeatsLength;
     2460                    if (maxRepeats > minRepeats) { /* Need this test as maxRepeats=-1 means no limit */
     2461                        repeatsLength = multiplyWithOverflowCheck(maxRepeats - minRepeats, duplength + 3 + 2 * LINK_SIZE);
     2462                        if (repeatsLength < 0) {
     2463                            errorcode = ERR16;
     2464                            return -1;
     2465                        }
     2466                        length += repeatsLength - (2 + 2 * LINK_SIZE);
     2467                    }
     2468                    if (length > MAX_PATTERN_SIZE) {
     2469                        errorcode = ERR16;
     2470                        return -1;
     2471                    }
    24322472                }
    24332473               
  • trunk/LayoutTests/ChangeLog

    r31384 r31388  
     12008-03-27  Mark Rowe  <mrowe@apple.com>
     2
     3        Reviewed by Adam Roben.
     4
     5        Tests for <rdar://problem/5826236> Regular expressions with large nested repetition counts can have their
     6        compiled length calculated incorrectly.
     7
     8        * fast/js/regexp-overflow-expected.txt:
     9        * fast/js/resources/regexp-overflow.js:
     10
    1112008-03-27  Brady Eidson  <beidson@apple.com>
    212
  • trunk/LayoutTests/fast/js/regexp-overflow-expected.txt

    r28787 r31388  
    1313PASS /{([\D-\ca]]„£µ+?)}|[[\B-\u00d4]√π- ]]]{0,3}/i.exec("B√π- ]]").toString() is "B√π- ]],"
    1414PASS /|[x\B-\u00b5]/i.exec("").toString() is ""
     15PASS new RegExp(s); threw exception SyntaxError: Invalid regular expression: regular expression too large.
     16PASS /(([ab]){30}){3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     17PASS /(([ab]){30}){0,3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     18PASS /(([ab]){30}){10,3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     19PASS /(([ab]){0,30}){3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     20PASS /(([ab]){0,30}){0,3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     21PASS /(([ab]){0,30}){10,3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     22PASS /(([ab]){10,30}){3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     23PASS /(([ab]){10,30}){0,3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     24PASS /(([ab]){10,30}){10,3360}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
     25PASS /(([ab]){12})(([ab]){65535}){1680}(([ab]){38}){722}([ab]){27}/ threw exception SyntaxError: Invalid regular expression: regular expression too large.
    1526
    1627PASS successfullyParsed is true
  • trunk/LayoutTests/fast/js/resources/regexp-overflow.js

    r28785 r31388  
    2121shouldBe('/|[x\\B-\\u00b5]/i.exec("").toString()', '""');
    2222
     23var s = "a";
     24for (var i = 0; i < 17; i++)
     25    s += s;
     26
     27shouldThrow('new RegExp(s);');
     28
     29shouldThrow('/(([ab]){30}){3360}/');
     30shouldThrow('/(([ab]){30}){0,3360}/');
     31shouldThrow('/(([ab]){30}){10,3360}/');
     32shouldThrow('/(([ab]){0,30}){3360}/');
     33shouldThrow('/(([ab]){0,30}){0,3360}/');
     34shouldThrow('/(([ab]){0,30}){10,3360}/');
     35shouldThrow('/(([ab]){10,30}){3360}/');
     36shouldThrow('/(([ab]){10,30}){0,3360}/');
     37shouldThrow('/(([ab]){10,30}){10,3360}/');
     38shouldThrow('/(([ab]){12})(([ab]){65535}){1680}(([ab]){38}){722}([ab]){27}/');
     39
    2340debug('');
    2441
Note: See TracChangeset for help on using the changeset viewer.