Closed Bug 1638154 Opened 2 months ago Closed 1 month ago

Assertion failure: is_uint24(cp_offset + eats_at_least), at new-regexp/regexp-bytecode-generator.cc:183

Categories

(Core :: JavaScript Engine, defect, P1)

x86_64
Linux
defect

Tracking

()

VERIFIED FIXED
mozilla78
Tracking Status
firefox-esr68 --- unaffected
firefox76 --- unaffected
firefox77 --- unaffected
firefox78 --- verified

People

(Reporter: decoder, Assigned: iain)

References

(Regression, )

Details

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

Attachments

(4 files)

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

See attachment.

Backtrace:

received signal SIGSEGV, Segmentation fault.
0x00005555569859ab in v8::internal::RegExpBytecodeGenerator::LoadCurrentCharacterImpl(int, v8::internal::Label*, bool, int, int) ()
#0  0x00005555569859ab in v8::internal::RegExpBytecodeGenerator::LoadCurrentCharacterImpl(int, v8::internal::Label*, bool, int, int) ()
#1  0x0000555556999b11 in v8::internal::RegExpNode::EmitQuickCheck(v8::internal::RegExpCompiler*, v8::internal::Trace*, v8::internal::Trace*, bool, v8::internal::Label*, v8::internal::QuickCheckDetails*, bool, v8::internal::ChoiceNode*) ()
#2  0x00005555569a0f39 in v8::internal::ChoiceNode::EmitChoices(v8::internal::RegExpCompiler*, v8::internal::AlternativeGenerationList*, int, v8::internal::Trace*, v8::internal::PreloadState*) ()
#3  0x000055555699e854 in v8::internal::ChoiceNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#4  0x00005555569a1ae0 in v8::internal::ActionNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#5  0x00005555569a1ae0 in v8::internal::ActionNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#6  0x000055555699deb7 in v8::internal::TextNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#7  0x000055555699deb7 in v8::internal::TextNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#8  0x00005555569a113c in v8::internal::ChoiceNode::EmitChoices(v8::internal::RegExpCompiler*, v8::internal::AlternativeGenerationList*, int, v8::internal::Trace*, v8::internal::PreloadState*) ()
#9  0x000055555699e854 in v8::internal::ChoiceNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#10 0x000055555699deb7 in v8::internal::TextNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#11 0x00005555569a1ae0 in v8::internal::ActionNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#12 0x000055555699deb7 in v8::internal::TextNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#13 0x000055555699deb7 in v8::internal::TextNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#14 0x000055555699deb7 in v8::internal::TextNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#15 0x00005555569a1ae0 in v8::internal::ActionNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#16 0x0000555556998137 in v8::internal::Trace::Flush(v8::internal::RegExpCompiler*, v8::internal::RegExpNode*) ()
#17 0x00005555569a1b52 in v8::internal::ActionNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#18 0x00005555569a1ae0 in v8::internal::ActionNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#19 0x00005555569a113c in v8::internal::ChoiceNode::EmitChoices(v8::internal::RegExpCompiler*, v8::internal::AlternativeGenerationList*, int, v8::internal::Trace*, v8::internal::PreloadState*) ()
#20 0x000055555699e854 in v8::internal::ChoiceNode::Emit(v8::internal::RegExpCompiler*, v8::internal::Trace*) ()
#21 0x0000555556997182 in v8::internal::RegExpCompiler::Assemble(v8::internal::Isolate*, v8::internal::RegExpMacroAssembler*, v8::internal::RegExpNode*, int, v8::internal::Handle<v8::internal::String>) ()
#22 0x0000555556981ff4 in js::irregexp::CompilePattern(JSContext*, JS::MutableHandle<js::RegExpShared*>, JS::Handle<JSLinearString*>, js::RegExpShared::CodeKind) ()
#23 0x0000555555cdd1e1 in js::RegExpShared::execute(JSContext*, JS::MutableHandle<js::RegExpShared*>, JS::Handle<JSLinearString*>, unsigned long, js::VectorMatchPairs*) ()
#24 0x00005555558b7ec6 in ExecuteRegExp(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSString*>, int, js::VectorMatchPairs*) ()
#25 0x00005555558b659e in js::RegExpMatcher(JSContext*, unsigned int, JS::Value*) ()
#26 0x000055555592be32 in CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), js::CallReason, JS::CallArgs const&) ()
[...]
#36 0x00005555557ad8f1 in Shell(JSContext*, js::cli::OptionParser*, char**) ()
#37 0x00005555557a4f58 in main ()
rax	0x5555570e652f	93825021142319
rbx	0xfffffff1	4294967281
rcx	0x555558088968	93825037535592
rdx	0x0	0
rsi	0x7ffff7105770	140737338431344
rdi	0x7ffff7104540	140737338426688
rbp	0x7fffffff8c00	140737488325632
rsp	0x7fffffff8be0	140737488325600
r8	0x7ffff7105770	140737338431344
r9	0x7ffff7f9bd40	140737353727296
r10	0x58	88
r11	0x7ffff6dac7a0	140737334921120
r12	0x7fffffff96d8	140737488328408
r13	0x26	38
r14	0x7ffff6086be0	140737321135072
r15	0x1	1
rip	0x5555569859ab <v8::internal::RegExpBytecodeGenerator::LoadCurrentCharacterImpl(int, v8::internal::Label*, bool, int, int)+443>
=> 0x5555569859ab <_ZN2v88internal23RegExpBytecodeGenerator24LoadCurrentCharacterImplEiPNS0_5LabelEbii+443>:	movl   $0xb7,0x0
   0x5555569859b6 <_ZN2v88internal23RegExpBytecodeGenerator24LoadCurrentCharacterImplEiPNS0_5LabelEbii+454>:	callq  0x555555835d6e <abort>

Marking s-s until investigated.

Attached file Testcase
Flags: needinfo?(iireland)
Regressed by: 1634135

This bug is internal to irregexp, and also triggers in a debug build of V8.

I'm not sure if it's exploitable, but unexpected things are happening in bounds-checking code, which is generally not a good sign. I've opened a security bug against Chromium (Issue 1083450).

Here's a reduced testcase:

source = "(?<=(?=ab)(|)abc)"
re = new RegExp(source);
re.exec("")
Flags: needinfo?(iireland)

Setting the severity to S3 for now, but if it is identified as exploitable, we should increase the severity appropriately

Severity: critical → S3
Priority: -- → P1

Looks like V8 landed a patch to fix this already, along with the comment:

Not a security issue since the actual code handles signed args just fine.

Not sure if the above statement is also true for Firefox, but perhaps we could make the same changes V8 just made.

Whiteboard: [bugmon:update,bisect] → [bugmon:update,bisected,confirmed]
Bugmon Analysis:
Verified bug as reproducible on mozilla-central 20200520100510-005ef1c25992.
The bug appears to have been introduced in the following build range:
> Start: 9e0ab86e29e39c3223f2adc07cf24920c4ad3e07 (20200511201544)
> End: ee1018a8611abdef625eba5f582189eefc824339 (20200511201754)
> Pushlog: https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=9e0ab86e29e39c3223f2adc07cf24920c4ad3e07&tochange=ee1018a8611abdef625eba5f582189eefc824339

This patch was auto-generated with new-regexp/import-irregexp.py.

Assignee: nobody → iireland
Status: NEW → ASSIGNED

Adding is_int24 is the only shim change necessary. While I was here, I took the opportunity to align is_uint24 to more closely match the V8 version (https://github.com/v8/v8/blob/a0d493e27e8bb3c643fbedc388350766e9f1f874/src/utils/utils.h#L426-L472).

Depends on D76250

Chrome team didn't think this was a security bug.

Group: javascript-core-security

Milliseconds after landing the parent patch, I realized that I had not actually uploaded the changes to address the review comments.

Status: ASSIGNED → RESOLVED
Closed: 1 month ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla78
Status: RESOLVED → VERIFIED
Keywords: bugmon
Bugmon Analysis:
Verified bug as fixed on rev mozilla-central 20200526023857-da2c7b0ac9a4.
Removing bugmon keyword as no further action possible.
Please review the bug and re-add the keyword for further analysis.
You need to log in before you can comment on or make changes to this bug.