[Webkit-unassigned] [Bug 220357] New: unexpected minimumInputSize in setupDisjunctionOffsets for regexp engine(yarr)
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Wed Jan 6 04:48:11 PST 2021
https://bugs.webkit.org/show_bug.cgi?id=220357
Bug ID: 220357
Summary: unexpected minimumInputSize in setupDisjunctionOffsets
for regexp engine(yarr)
Product: WebKit
Version: WebKit Local Build
Hardware: All
OS: All
Status: NEW
Severity: Normal
Priority: P2
Component: JavaScriptCore
Assignee: webkit-unassigned at lists.webkit.org
Reporter: raycp at protonmail.com
first of all, the poc is shown as below:
```
function main() {
let v30 = '4{4294967294}0'
const v32 = RegExp(v30);
}
main();
```
which will cause the crash in `debug` version of jsc and it won't happen in `release` version of jsc
```
$ ./WebKitBuild/Debug/bin/jsc poc.js
ASSERTION FAILED: minimumInputSize != UINT_MAX
../../Source/JavaScriptCore/yarr/YarrPattern.cpp(937) : JSC::Yarr::ErrorCode JSC::Yarr::YarrPatternConstructor::setupDisjunctionOffsets(JSC::Yarr::PatternDisjunction*, unsigned int, unsigned int, unsigned int&)
[1] 2098538 abort ./WebKitBuild/Debug/bin/jsc
$ ./WebKitBuild/Release/bin/jsc poc.js
```
the call stack is show as below:
```
#1 0x00007ffff2236859 in __GI_abort () at abort.c:79
#2 0x00005555555d5fff in CRASH_WITH_INFO(...) () at DerivedSources/ForwardingHeaders/wtf/Assertions.h:713
#3 0x00007ffff67430cd in JSC::Yarr::YarrPatternConstructor::setupDisjunctionOffsets (this=0x7fffffffc950, disjunction=0x7fffef9afed8, initialCallFrameSize=0, initialInputPosition=0, callFrameSize=@0x7fffffffc914: 32767) at ../../Source/JavaScriptCore/yarr/YarrPattern.cpp:937
#4 0x00007ffff674318d in JSC::Yarr::YarrPatternConstructor::setupOffsets (this=0x7fffffffc950) at ../../Source/JavaScriptCore/yarr/YarrPattern.cpp:951
#5 0x00007ffff66d480c in JSC::Yarr::YarrPattern::compile (this=0x7fffffffca60, patternString=...) at ../../Source/JavaScriptCore/yarr/YarrPattern.cpp:1131
#6 0x00007ffff66d4a68 in JSC::Yarr::YarrPattern::YarrPattern (this=0x7fffffffca60, pattern=..., flags=..., error=@0x7fffef9fcc5a: JSC::Yarr::ErrorCode::NoError) at ../../Source/JavaScriptCore/yarr/YarrPattern.cpp:1151
#7 0x00007ffff6332ae4 in JSC::RegExp::finishCreation (this=0x7fffef9fcc48, vm=...) at ../../Source/JavaScriptCore/runtime/RegExp.cpp:170
#8 0x00007ffff6332d78 in JSC::RegExp::createWithoutCaching (vm=..., patternString=..., flags=...) at ../../Source/JavaScriptCore/runtime/RegExp.cpp:207
#9 0x00007ffff633b707 in JSC::RegExpCache::lookupOrCreate (this=0x7fffef9d0000, patternString=..., flags=...) at ../../Source/JavaScriptCore/runtime/RegExpCache.cpp:42
#10 0x00007ffff6332dd1 in JSC::RegExp::create (vm=..., patternString=..., flags=...) at ../../Source/JavaScriptCore/runtime/RegExp.cpp:213
#11 0x00007ffff633cf59 in JSC::regExpCreate (globalObject=0x7fffaf5fa068, newTarget=..., patternArg=..., flagsArg=...) at ../../Source/JavaScriptCore/runtime/RegExpConstructor.cpp:249
#12 0x00007ffff633d540 in JSC::constructRegExp (globalObject=0x7fffaf5fa068, args=..., callee=0x7fffef9fcba8, newTarget=...) at ../../Source/JavaScriptCore/runtime/RegExpConstructor.cpp:309
#13 0x00007ffff633d77d in JSC::callRegExpConstructor (globalObject=0x7fffaf5fa068, callFrame=0x7fffffffce70) at ../../Source/JavaScriptCore/runtime/RegExpConstructor.cpp:334
#14 0x00007fffaf8ff027 in ?? ()
#15 0x00007fffffffcf10 in ?? ()
#16 0x00007ffff4dc9db1 in llint_op_call () at /home/raycp/Desktop/WebKit/Source/JavaScriptCore/llint/LowLevelInterpreter.asm:1092
#17 0x0000000000000000 in ?? ()
```
when i finished analysis of the bug, i found that the root cause code is in `setupDisjunctionOffsets` function belong to the yarr engine. the code caused the crash is `ASSERT(minimumInputSize != UINT_MAX)`. The regexp pattern's(`'4{4294967294}0'`) length is `0xffffffff` after setupAlternativeOffsets function call, which means `minimumInputSize` equal to `0xffffffff`. But in the assert code, it can't allow `minimumInputSize` equal to `0xffffffff`, so it goes crash.
```
// yarr/YarrPattern.cpp: 911
ErrorCode setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition, unsigned& callFrameSize)
{
if (UNLIKELY(!isSafeToRecurse()))
return ErrorCode::TooManyDisjunctions;
if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative;
unsigned minimumInputSize = UINT_MAX;
unsigned maximumCallFrameSize = 0;
bool hasFixedSize = true;
ErrorCode error = ErrorCode::NoError;
for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
PatternAlternative* alternative = disjunction->m_alternatives[alt].get();
unsigned currentAlternativeCallFrameSize;
error = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition, currentAlternativeCallFrameSize);
if (hasError(error))
return error;
minimumInputSize = std::min(minimumInputSize, alternative->m_minimumSize);
maximumCallFrameSize = std::max(maximumCallFrameSize, currentAlternativeCallFrameSize);
hasFixedSize &= alternative->m_hasFixedSize;
if (alternative->m_minimumSize > INT_MAX)
m_pattern.m_containsUnsignedLengthPattern = true;
}
ASSERT(minimumInputSize != UINT_MAX);
ASSERT(maximumCallFrameSize >= initialCallFrameSize);
disjunction->m_hasFixedSize = hasFixedSize;
disjunction->m_minimumSize = minimumInputSize;
disjunction->m_callFrameSize = maximumCallFrameSize;
callFrameSize = maximumCallFrameSize;
return error;
}
```
the `minimumInputSize` can equal to `0xffffffff` may break the assumption of `jit`, and i think it may cause serious security problem.
so i report the bug
--
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20210106/baf76638/attachment-0001.htm>
More information about the webkit-unassigned
mailing list