Closed Bug 1691184 Opened 5 years ago Closed 5 years ago

Crash [@ v8::internal::IrregexpInterpreter::Result v8::internal::(anonymous namespace)::RawMatch]

Categories

(Core :: JavaScript Engine, defect, P1)

x86_64
Linux
defect

Tracking

()

VERIFIED FIXED
88 Branch
Tracking Status
firefox-esr78 --- wontfix
firefox86 --- wontfix
firefox87 --- wontfix
firefox88 --- verified

People

(Reporter: decoder, Assigned: iain)

References

(Regression)

Details

(Keywords: crash, regression, testcase, Whiteboard: [bugmon:update,bisected,confirmed])

Crash Data

Attachments

(2 files)

The following testcase crashes on mozilla-central revision 20210203-ca7a3f92939d (debug build, run with --fuzzing-safe --no-threads):

s0 = " ";
timeout(1);
r = new RegExp('(((^)]))','');
try {
  for(;;) s0+=s0;
} catch(exc) {}
startgc(7,'shrinking');
s0.match(r);

Backtrace:

received signal SIGSEGV, Segmentation fault.
#0  0x0000555557551c1f in v8::internal::IrregexpInterpreter::Result v8::internal::(anonymous namespace)::RawMatch<unsigned char>(v8::internal::Isolate*, v8::internal::ByteArray, v8::internal::String, v8::internal::Vector<unsigned char const>, int*, int, int, int, unsigned int, v8::internal::RegExp::CallOrigin, unsigned int) ()
#1  0x00005555575516ec in v8::internal::IrregexpInterpreter::MatchInternal(v8::internal::Isolate*, v8::internal::ByteArray, v8::internal::String, int*, int, int, int, v8::internal::RegExp::CallOrigin, unsigned int) ()
#2  0x000055555755148f in v8::internal::IrregexpInterpreter::Match(v8::internal::Isolate*, v8::internal::JSRegExp, v8::internal::String, int*, int, int, v8::internal::RegExp::CallOrigin) ()
#3  0x000055555755a445 in v8::internal::IrregexpInterpreter::MatchForCallFromRuntime(v8::internal::Isolate*, v8::internal::Handle<v8::internal::JSRegExp>, v8::internal::Handle<v8::internal::String>, int*, int, int) ()
#4  0x000055555751557d in js::irregexp::Interpret(JSContext*, JS::MutableHandle<js::RegExpShared*>, JS::Handle<JSLinearString*>, unsigned long, js::VectorMatchPairs*) ()
#5  0x00005555575157b2 in js::irregexp::Execute(JSContext*, JS::MutableHandle<js::RegExpShared*>, JS::Handle<JSLinearString*>, unsigned long, js::VectorMatchPairs*) ()
#6  0x0000555556f33a1b in js::RegExpShared::execute(JSContext*, JS::MutableHandle<js::RegExpShared*>, JS::Handle<JSLinearString*>, unsigned long, js::VectorMatchPairs*) ()
#7  0x0000555556b1f975 in ExecuteRegExp(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSString*>, int, js::VectorMatchPairs*) ()
#8  0x0000555556b1e1ea in RegExpMatcherImpl(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSString*>, int, JS::MutableHandle<JS::Value>) ()
#9  0x0000555556b1dda2 in js::RegExpMatcher(JSContext*, unsigned int, JS::Value*) ()
#10 0x0000555556b96802 in CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), js::CallReason, JS::CallArgs const&) ()
#11 0x0000555556b96082 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) ()
#12 0x0000555556b973a1 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) ()
#13 0x0000555556b8a8d4 in Interpret(JSContext*, js::RunState&) ()
#14 0x0000555556b815a8 in js::RunScript(JSContext*, js::RunState&) ()
#15 0x0000555556b96021 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) ()
#16 0x0000555556b973a1 in InternalCall(JSContext*, js::AnyInvokeArgs const&, js::CallReason) ()
#17 0x00005555575ab2a9 in js::jit::DoCallFallback(JSContext*, js::jit::BaselineFrame*, js::jit::ICCall_Fallback*, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) ()
#18 0x0000391148b28ba3 in ?? ()
[...]
#46 0x0000000000000000 in ?? ()
rax	0x0	0
rbx	0x7fffffffa340	140737488331584
rcx	0x7fffffffa440	140737488331840
rdx	0x7fffffffa440	140737488331840
rsi	0xfffb000000000000	-1407374883553280
rdi	0x7fffffffa340	140737488331584
rbp	0x7fffffffa5b0	140737488332208
rsp	0x7fffffffa290	140737488331408
r8	0x20000000	536870912
r9	0x7fffffffa940	140737488333120
r10	0x7ffff6b00000	140737332117504
r11	0x4	4
r12	0xa	10
r13	0x4	4
r14	0x7fffffffa610	140737488332304
r15	0x8	8
rip	0x555557551c1f <v8::internal::IrregexpInterpreter::Result v8::internal::(anonymous namespace)::RawMatch<unsigned char>(v8::internal::Isolate*, v8::internal::ByteArray, v8::internal::String, v8::internal::Vector<unsigned char const>, int*, int, int, int, unsigned int, v8::internal::RegExp::CallOrigin, unsigned int)+319>
=> 0x555557551c1f <_ZN2v88internal12_GLOBAL__N_18RawMatchIhEENS0_19IrregexpInterpreter6ResultEPNS0_7IsolateENS0_9ByteArrayENS0_6StringENS0_6VectorIKT_EEPiiiijNS0_6RegExp10CallOriginEj+319>:	mov    0x0(%r13),%r14d
   0x555557551c23 <_ZN2v88internal12_GLOBAL__N_18RawMatchIhEENS0_19IrregexpInterpreter6ResultEPNS0_7IsolateENS0_9ByteArrayENS0_6StringENS0_6VectorIKT_EEPiiiijNS0_6RegExp10CallOriginEj+323>:	mov    %r14d,%ecx

Likely a null-deref due to an earlier OOM, but marking s-s until investigated.

Attached file Testcase

Not s-s, but good catch.

If an interrupt occurs during regexp execution, we return up the stack to RegExpShared::execute to handle it, then try again. Normally it is safe to GC and discard jitcode at this point, because we can fall back to interpreted bytecode (which is not discarded). However, if the input string is long enough, then we jump straight to compilation without producing bytecode. In that case, when we resume, we will have neither bytecode nor jitcode, and end up dereferencing a null pointer.

Group: javascript-core-security

Bugmon Analysis:
Verified bug as reproducible on mozilla-central 20210208214800-566f81bfa373.
The bug appears to have been introduced in the following build range:

Start: 256602905ce82b1866a1d2f37b409fa768fb7ae6 (20200513145103)
End: d1114574b777bb00b85f73733a8bd6a78d2ad87e (20200513215059)
Pushlog: https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=256602905ce82b1866a1d2f37b409fa768fb7ae6&tochange=d1114574b777bb00b85f73733a8bd6a78d2ad87e

Whiteboard: [bugmon:update,bisect] → [bugmon:update,bisected,confirmed]

If an interrupt occurs during regexp execution, we return up the stack to RegExpShared::execute to handle it, then try again. Normally it's safe (if slow) to GC and discard jitcode at this point, because we can fall back to interpreted bytecode (which is not discarded). However, if the input string is long enough, then we jump straight to compilation without producing bytecode. In that case, when we resume, we will have neither bytecode nor jitcode, and end up dereferencing a null pointer.

The fix is to recompile after handling the interrupt. In addition to fixing the crash, forcing compilation here should improve our chance of eventual success (compared to resuming in the regexp interpreter).

Assignee: nobody → iireland
Status: NEW → ASSIGNED
Severity: -- → S3
Priority: -- → P1
Pushed by iireland@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/e3a59a1dc7ca Recompile if necessary before retrying interrupted regexp r=mgaudet

There's a r+ patch which didn't land and no activity in this bug for 2 weeks.
:iain, could you have a look please?
For more information, please visit auto_nag documentation.

Flags: needinfo?(mgaudet)
Flags: needinfo?(iireland)

The testcase ended up being flaky. It's in a corner case that we currently don't have good infrastructure for testing; opened up bug 1697077 to address that.

Flags: needinfo?(mgaudet)
Flags: needinfo?(iireland)
Pushed by iireland@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/69abc9909b54 Recompile if necessary before retrying interrupted regexp r=mgaudet
Status: ASSIGNED → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → 88 Branch

Bugmon Analysis:
Verified bug as fixed on rev mozilla-central 20210310093927-056c2a428e2d.
Removing bugmon keyword as no further action possible.
Please review the bug and re-add the keyword for further analysis.

Status: RESOLVED → VERIFIED
Keywords: bugmon
Has Regression Range: --- → yes
Crash Signature: [@ v8::internal::IrregexpInterpreter::Result v8::internal::(anonymous namespace)::RawMatch] → [@ v8::internal::IrregexpInterpreter::Result v8::internal::(anonymous namespace)::RawMatch] [@ v8::internal::(anonymous namespace)::RawMatch<T>]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: