WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
292939
[JSC] ASSERTION FAILED: codeBlock->canGetCodeOrigin(index)
https://bugs.webkit.org/show_bug.cgi?id=292939
Summary
[JSC] ASSERTION FAILED: codeBlock->canGetCodeOrigin(index)
rhezashan
Reported
2025-05-13 10:02:22 PDT
I'm filling as security for precaution. Tested on latest Webkit @main Debug ``` commit 8016724906a1de17b5e868edba4e93a6615a9aa7 (HEAD -> main, origin/main, origin/HEAD) Author: Alex Christensen <
achristensen@apple.com
> Date: Mon May 12 18:12:15 2025 -0700 -- bisection Last good version:
289982@main
First bad version:
289983@main
Last bad version: @main -- repro ./jsc --useFTLJIT=0 --slowPathAllocsBetweenGCs=100 --forceDebuggerBytecodeGeneration=1 --forceEagerCompilation=1 ./ori.js ``` ASSERTION FAILED: codeBlock->canGetCodeOrigin(index) ./interpreter/StackVisitor.cpp(152) : void JSC::StackVisitor::readFrame(CallFrame *) 1 0x11fbc3d6e JSC::StackVisitor::readFrame(JSC::CallFrame*) 2 0x11fbc3926 JSC::StackVisitor::StackVisitor(JSC::CallFrame*, JSC::VM&, bool) 3 0x11fbc40f4 JSC::StackVisitor::StackVisitor(JSC::CallFrame*, JSC::VM&, bool) 4 0x11fbc1475 void JSC::StackVisitor::visit<(JSC::StackVisitor::EmptyEntryFrameAction)0, JSC::ShadowChicken::update(JSC::VM&, JSC::CallFrame*)::$_0>(JSC::CallFrame*, JSC::VM&, JSC::ShadowChicken::update(JSC::VM&, JSC::CallFrame*)::$_0 const&, bool) 5 0x11fbc0638 JSC::ShadowChicken::update(JSC::VM&, JSC::CallFrame*) 6 0x11f672781 JSC::Heap::stopThePeriphery(JSC::GCConductor) 7 0x11f668226 JSC::Heap::finishChangingPhase(JSC::GCConductor) 8 0x11f66c3cc JSC::Heap::changePhase(JSC::GCConductor, JSC::CollectorPhase) 9 0x11f668403 JSC::Heap::runNotRunningPhase(JSC::GCConductor) 10 0x11f667203 JSC::Heap::runCurrentPhase(JSC::GCConductor, JSC::CurrentThreadState*) 11 0x11f6733a0 JSC::Heap::collectInMutatorThread() 12 0x11f67315c JSC::Heap::stopIfNecessarySlow(unsigned int) 13 0x11f675107 void JSC::Heap::waitForCollector<JSC::Heap::waitForCollection(unsigned long long)::$_0>(JSC::Heap::waitForCollection(unsigned long long)::$_0 const&) 14 0x11f666d47 JSC::Heap::waitForCollection(unsigned long long) 15 0x11f666036 JSC::Heap::collectSync(JSC::GCRequest) 16 0x11f66624c JSC::Heap::collectNow(JSC::Synchronousness, JSC::GCRequest) 17 0x11f7c706f JSC::LocalAllocator::doTestCollectionsIfNeeded(JSC::Heap&, JSC::GCDeferralContext*) 18 0x11f7c6886 JSC::LocalAllocator::allocateSlowCase(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) 19 0x1205e8248 JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode)::'lambda'()::operator()() const 20 0x11d49925a JSC::HeapCell* JSC::FreeList::allocateWithCellSize<JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode)::'lambda'()>(JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode)::'lambda'() const&, unsigned long) 21 0x11d498fe2 JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) 22 0x11d498cc1 JSC::Allocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) const 23 0x11d498994 JSC::CompleteSubspace::allocate(JSC::VM&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) 24 0x11f090801 JSC::Butterfly::createUninitialized(JSC::VM&, JSC::JSObject*, unsigned long, unsigned long, bool, unsigned long) 25 0x1207cbbb6 JSC::Butterfly::createOrGrowPropertyStorage(JSC::Butterfly*, JSC::VM&, JSC::JSObject*, JSC::Structure*, unsigned long, unsigned long) 26 0x1207cb965 JSC::JSObject::allocateMoreOutOfLineStorage(JSC::VM&, unsigned long, unsigned long) 27 0x11fdcabf9 operationReallocateButterflyAndTransition 28 0x2f21a0136 27 ??? 0x00000002f21a0136 0x0 + 12651725110 29 0x12232ee86 llint_call_javascript 30 0x11fbb7ce5 JSC::Interpreter::executeProgram(JSC::SourceCode const&, JSC::JSGlobalObject*, JSC::JSObject*) 31 0x12023171c JSC::evaluate(JSC::JSGlobalObject*, JSC::SourceCode const&, JSC::JSValue, WTF::NakedPtr<JSC::Exception>&) zsh: illegal hardware instruction ./jsc --useFTLJIT=0 --slowPathAllocsBetweenGCs=100 --forceEagerCompilation=1 Using `ori_heap.js` I've discovered a memory corruption vulnerability in JavaScriptCore that I've been debugging with LLDB. Here's what I've found so far: During garbage collection, a `CodeBlock object's` vtable pointer gets corrupted with invalid values. The corruption follows a specific pattern where the high byte cycles (0x01, 0x00, 0x02, 0x00) while the rest remains constant: ``` First observation: 0x0100120000005210 Second observation: 0x0000120000005210 Third observation: 0x0200120000005210 Later cycles back to previous values ``` The rest of the CodeBlock remains intact (magic number `0xc0deb10c`, valid VM pointer). The corruption happens during Heap::stopThePeriphery when ShadowChicken tries to walk the stack. Despite the corruption, execution continues through multiple GC cycles. The bug is triggered by JavaScript code that creates ArrayBuffers and performs BigInt operations. I've tried to use memory spraying to gain control over the corrupted value, but haven't yet demonstrated direct control. ---------------------------------------------------------------------- for the evidance, please use `ori_hack2.js` and `analyze_vtable.py` on lldb 1. lldb -- ./jsc --useFTLJIT=0 --slowPathAllocsBetweenGCs=100 --forceDebuggerBytecodeGeneration=1 --forceEagerCompilation=1 ./ori_hack2.js 2. (lldb) breakpoint set --file StackVisitor.cpp --line 152 3. (lldb) command script import ./analyze_vtable.py 4. (lldb) run 5. (lldb) analyze_vtable the output === VTABLE CORRUPTION EVIDENCE === CodeBlock address: 0x000062d0000fe2c0 Vtable pointer: 0x0000120000005210 High byte: 0x00, Second byte: 0x00 Pattern does not match expected markers, but may still be corrupted Magic number: 0xc0deb10c (should be 0xc0deb10c) Magic number is intact - confirms selective vtable corruption only === END EVIDENCE === (lldb) p/x *(void**)codeBlock (void *) 0x0000120000005210 (lldb) x/20gx codeBlock 0x62d0000fe2c0: 0x0000120000005210 0x0000620000000108 0x62d0000fe2d0: 0x0000000a00c30100 0x0000000200000006 0x62d0000fe2e0: 0x0000000000000000 0x0000003d00000000 0x62d0000fe2f0: 0x00000000fffffffa 0x000062d000158ae0 0x62d0000fe300: 0x000062d000092780 0x0000000102bf5800 0x62d0000fe310: 0x0000606000019fa0 0x000060e00004ae20 0x62d0000fe320: 0x000060e00004a9c0 0x0000000000000000 0x62d0000fe330: 0x0000000000000000 0x0000000000000000 0x62d0000fe340: 0x0000602000057e90 0x000061400000bc40 0x62d0000fe350: 0x0000608000016d20 0x000061200006f800 (lldb) p/x codeBlock->m_magic (uint32_t) 0xc0deb10c
Attachments
poc
(1.55 KB, text/javascript)
2025-05-13 10:02 PDT
,
rhezashan
no flags
Details
ori_heap.js
(2.95 KB, text/javascript)
2025-05-13 10:03 PDT
,
rhezashan
no flags
Details
ori_hack2.js
(11.23 KB, text/javascript)
2025-05-13 10:03 PDT
,
rhezashan
no flags
Details
analyze_vtable.py
(2.63 KB, text/x-python-script)
2025-05-13 10:03 PDT
,
rhezashan
no flags
Details
View All
Add attachment
proposed patch, testcase, etc.
rhezashan
Comment 1
2025-05-13 10:02:46 PDT
Created
attachment 475213
[details]
poc
Radar WebKit Bug Importer
Comment 2
2025-05-13 10:02:48 PDT
<
rdar://problem/151233525
>
rhezashan
Comment 3
2025-05-13 10:03:06 PDT
Created
attachment 475214
[details]
ori_heap.js
rhezashan
Comment 4
2025-05-13 10:03:24 PDT
Created
attachment 475215
[details]
ori_hack2.js
rhezashan
Comment 5
2025-05-13 10:03:54 PDT
Created
attachment 475216
[details]
analyze_vtable.py
rhezashan
Comment 6
2025-05-14 19:25:17 PDT
Update: Following the error stack on macOS, it's seems identically with the error stack above(macOS X86_64) ```
rheza@rhezas-MacBook-Pro.local
:~/WebKit/WebKitBuild/Debug ./jsc --useFTLJIT=0 --slowPathAllocsBetweenGCs=100 --forceDebuggerBytecodeGeneration=1 --forceEagerCompilation=1 ~/poc.js jsc(6908,0x208f60c80) malloc: nano zone abandoned due to inability to reserve vm space. ASSERTION FAILED: codeBlock->canGetCodeOrigin(index) ./interpreter/StackVisitor.cpp(152) : void JSC::StackVisitor::readFrame(CallFrame *) 1 0x11a328bdc JSC::StackVisitor::readFrame(JSC::CallFrame*) 2 0x11a328730 JSC::StackVisitor::StackVisitor(JSC::CallFrame*, JSC::VM&, bool) 3 0x11a328f80 JSC::StackVisitor::StackVisitor(JSC::CallFrame*, JSC::VM&, bool) 4 0x11a32621c void JSC::StackVisitor::visit<(JSC::StackVisitor::EmptyEntryFrameAction)0, JSC::ShadowChicken::update(JSC::VM&, JSC::CallFrame*)::$_0>(JSC::CallFrame*, JSC::VM&, JSC::ShadowChicken::update(JSC::VM&, JSC::CallFrame*)::$_0 const&, bool) 5 0x11a325548 JSC::ShadowChicken::update(JSC::VM&, JSC::CallFrame*) 6 0x119dd8704 JSC::Heap::stopThePeriphery(JSC::GCConductor) 7 0x119dce93c JSC::Heap::finishChangingPhase(JSC::GCConductor) 8 0x119dd23d0 JSC::Heap::changePhase(JSC::GCConductor, JSC::CollectorPhase) 9 0x119dceb48 JSC::Heap::runNotRunningPhase(JSC::GCConductor) 10 0x119dcd9d0 JSC::Heap::runCurrentPhase(JSC::GCConductor, JSC::CurrentThreadState*) 11 0x119dd9460 JSC::Heap::collectInMutatorThread() 12 0x119dd91bc JSC::Heap::stopIfNecessarySlow(unsigned int) 13 0x119ddb3f8 void JSC::Heap::waitForCollector<JSC::Heap::waitForCollection(unsigned long long)::$_0>(JSC::Heap::waitForCollection(unsigned long long)::$_0 const&) 14 0x119dcd478 JSC::Heap::waitForCollection(unsigned long long) 15 0x119dcc720 JSC::Heap::collectSync(JSC::GCRequest) 16 0x119dcc934 JSC::Heap::collectNow(JSC::Synchronousness, JSC::GCRequest) 17 0x119f3bcb8 JSC::LocalAllocator::doTestCollectionsIfNeeded(JSC::Heap&, JSC::GCDeferralContext*) 18 0x119f3b558 JSC::LocalAllocator::allocateSlowCase(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) 19 0x119885948 JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode)::'lambda'()::operator()() const 20 0x11a84efdc JSC::HeapCell* JSC::FreeList::allocateWithCellSize<JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode)::'lambda'()>(JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode)::'lambda'() const&, unsigned long) 21 0x11a84ec1c JSC::LocalAllocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) 22 0x11a851790 JSC::Allocator::allocate(JSC::Heap&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) const 23 0x11a85152c JSC::CompleteSubspace::allocate(JSC::VM&, unsigned long, JSC::GCDeferralContext*, JSC::AllocationFailureMode) 24 0x1198087b4 JSC::Butterfly::createUninitialized(JSC::VM&, JSC::JSObject*, unsigned long, unsigned long, bool, unsigned long) 25 0x11aedbf54 JSC::Butterfly::createOrGrowPropertyStorage(JSC::Butterfly*, JSC::VM&, JSC::JSObject*, JSC::Structure*, unsigned long, unsigned long) 26 0x11aedbd5c JSC::JSObject::allocateMoreOutOfLineStorage(JSC::VM&, unsigned long, unsigned long) 27 0x11a53d9b8 operationReallocateButterflyAndTransition 28 0x128ec4288 27 ??? 0x0000000128ec4288 0x0 + 4981539464 29 0x11c898554 llint_call_javascript 30 0x11a31d10c JSC::Interpreter::executeProgram(JSC::SourceCode const&, JSC::JSGlobalObject*, JSC::JSObject*) 31 0x11a9ca95c JSC::evaluate(JSC::JSGlobalObject*, JSC::SourceCode const&, JSC::JSValue, WTF::NakedPtr<JSC::Exception>&) zsh: trace trap ./jsc --useFTLJIT=0 --slowPathAllocsBetweenGCs=100 --forceEagerCompilation=1
rheza@rhezas-MacBook-Pro.local
:~/WebKit/WebKitBuild/Debug sw_vers ProductName: macOS ProductVersion: 15.4.1 BuildVersion: 24E263
rheza@rhezas-MacBook-Pro.local
:~/WebKit/WebKitBuild/Debug git loq git: 'loq' is not a git command. See 'git --help'. The most similar command is log
rheza@rhezas-MacBook-Pro.local
:~/WebKit/WebKitBuild/Debug git log commit 37a5e03d2e2fa234e69a4a35b23cc0a538985f2e (HEAD -> main, origin/main, origin/HEAD) Author: Geoffrey Garen <
ggaren@apple.com
> Date: Wed May 14 18:43:59 2025 -0700
Yusuke Suzuki
Comment 7
2025-05-28 03:09:25 PDT
Pull request:
https://github.com/WebKit/WebKit/pull/45989
Yusuke Suzuki
Comment 8
2025-05-28 03:10:07 PDT
OK, this was not a security issue. We gracefully stop stack visiting when we found it is not a usable CallSiteIndex.
EWS
Comment 9
2025-05-28 15:33:56 PDT
Committed
295518@main
(17dac674cab9): <
https://commits.webkit.org/295518@main
> Reviewed commits have been landed. Closing PR #45989 and removing active labels.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug