Changeset 294411 in webkit


Ignore:
Timestamp:
May 18, 2022, 11:33:44 AM (3 years ago)
Author:
msaboff@apple.com
Message:

WTF::CrashOnOverflow::crash() with /((a{100000000})*b{2100000000})+/.test();
https://bugs.webkit.org/show_bug.cgi?id=240552

Reviewed by Yusuke Suzuki and Alex Christensen.

Replaced a crashing checked add in the YARR JIT code generator with a reporting add so we can
catch the overflow. When we do overflow, we terminate the JIT genration with an error.
We'll fallback to the YARR interpreter, which already exits with an error on a similar overflow.

  • JSTests/stress/regexp-large-quantifier.js:

(testRegExp):

  • Source/JavaScriptCore/yarr/YarrJIT.cpp:

(JSC::Yarr::dumpCompileFailure):

  • Source/JavaScriptCore/yarr/YarrJIT.h:

Canonical link: https://commits.webkit.org/250703@main

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/stress/regexp-large-quantifier.js

    r233451 r294411  
    1 function testRegExp(pattern, string, expectedMatch) {
     1function testRegExp(pattern, string, expectedParseError, expectedMatch) {
    22    const r = new RegExp(pattern);
    3     const actualResult = r.exec(string);
     3    let actualResult = null;
     4    let actualParseError = null;
     5    try {
     6        actualResult = r.exec(string);
     7    } catch(e) {
     8        actualParseError = e;
     9    }
     10
     11    if (expectedParseError && expectedParseError != actualParseError)
     12        throw("Expected \"" + expectedParseError + "\", but got \"" + actualParseError + "\"");
     13
    414    if (expectedMatch === undefined) {
    515        if (actualResult !== null)
     
    1121}
    1222
    13 testRegExp("a{0,4294967295}", "a", "a");
    14 testRegExp("a{0,4294967296}", "a", "a");
    15 testRegExp("^a{0,4294967296}$", "a{0,4294967296}", undefined);
    16 testRegExp("(?:a{0,340282366920}?){0,1}a", "aa", "aa");
     23testRegExp("a{0,4294967295}", "a", undefined, "a");
     24testRegExp("a{0,4294967296}", "a", undefined, "a");
     25testRegExp("^a{0,4294967296}$", "a{0,4294967296}", undefined, undefined);
     26testRegExp("(?:a{0,340282366920}?){0,1}a", "aa", undefined, "aa");
     27testRegExp("((.{100000000})*.{2100000000})+", "x", "SyntaxError: Invalid regular expression: pattern exceeds string length limits", undefined);
  • trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp

    r291997 r294411  
    35973597                if ((term->quantityType == QuantifierType::FixedCount) && (term->type != PatternTerm::Type::ParentheticalAssertion))
    35983598                    lastOp.m_checkAdjust -= disjunction->m_minimumSize;
    3599                 lastOp.m_checkedOffset = checkedOffset + lastOp.m_checkAdjust;
     3599
     3600                Checked<unsigned, RecordOverflow> checkedOffsetResult(checkedOffset);
     3601                checkedOffsetResult += lastOp.m_checkAdjust;
     3602
     3603                if (UNLIKELY(checkedOffsetResult.hasOverflowed())) {
     3604                    m_failureReason = JITFailureReason::OffsetTooLarge;
     3605                    return;
     3606                }
     3607
     3608                lastOp.m_checkedOffset = checkedOffsetResult;
    36003609            }
    36013610            opCompileAlternative(m_ops[lastOpIndex].m_checkedOffset, nestedAlternative);
     
    47224731        dataLog("Can't JIT because of failure of allocation of executable memory\n");
    47234732        break;
     4733    case JITFailureReason::OffsetTooLarge:
     4734        dataLog("Can't JIT because pattern exceeds string length limits\n");
     4735        break;
    47244736    }
    47254737}
  • trunk/Source/JavaScriptCore/yarr/YarrJIT.h

    r291972 r294411  
    6363    ParenthesisNestedTooDeep,
    6464    ExecutableMemoryAllocationFailure,
     65    OffsetTooLarge,
    6566};
    6667
Note: See TracChangeset for help on using the changeset viewer.