[17] [JSC] Save source offset for evaluating Wasm constant expressions
Severity: Medium | Component: JSC WebAssembly module loader | b05d16f
Rated Medium because the observable effect is one uninitialised 64-bit stack word leaked per failed extended-const-expr evaluation via WebAssembly.RuntimeError.message, sufficient as an info-leak primitive (e.g., to defeat ASLR) but not a read-of-attacker-chosen-address primitive.
Source/JavaScriptCore/wasm/WasmConstExprGenerator.cpp
- ConstExprGenerator(Mode mode, const ModuleInformation& info, JSWebAssemblyInstance* instance)
+ ConstExprGenerator(Mode mode, size_t offsetInSource, const ModuleInformation& info, JSWebAssemblyInstance* instance)
: m_mode(mode)
+ , m_offsetInSource(offsetInSource)
, m_info(info)
, m_instance(instance)
...
Mode m_mode;
- size_t m_offsetInSource;
+ size_t m_offsetInSource { 0 };
Patch Details
The Evaluate-mode constructor of ConstExprGenerator gains an offsetInSource parameter, threaded through evaluateExtendedConstExpr and WebAssemblyModuleRecord::evaluateConstantExpression. ModuleInformation::constantExpressions becomes Vector<std::pair<Vector<uint8_t>, size_t>> (typedef ConstantExpressionAndSourceOffset); SectionParser::parseInitExpr records initialOffset + m_offsetInSource alongside the expression bytes. As defence-in-depth, m_offsetInSource gains a { 0 } default initializer, replacing the previous uninitialised declaration.
Uninitialized member of a stack-allocated object reaches a web-visible error string via integer-to-text formatting.
Background
Wasm extended constant expressions (the GC / ext-const proposal) allow operations beyond simple constants in initializer positions — array.new, struct.new, i32.add. They are parsed at module compile time and re-executed at instance creation, because their result depends on imports/globals. JSC routes both phases through ConstExprGenerator with two modes: Validate (during SectionParser::parseInitExpr) and Evaluate (during WebAssemblyModuleRecord::evaluateConstantExpression). Each phase shares a fail() helper that formats WebAssembly.Module doesn't parse at byte N: ... using m_parser->offset() + m_offsetInSource. Failures inside fail() become the .message of a JSWebAssemblyRuntimeError thrown to JS.
Analysis
ConstExprGenerator::m_offsetInSource was declared without an initializer. Only the Validate-mode constructor took an offsetInSource parameter; the Evaluate-mode constructor did not assign it. ConstExprGenerator is stack-allocated inside evaluateExtendedConstExpr, so the field held arbitrary stack data from prior frames.
Aaaa Aaaaaaaaaa Aa Aa Aaaaaaaa Aaaaaaaa Aaaaaaaaaa Aaaaaa Aaaaaaaaaaaa Aaaa Aaaaaaaa Aaaaa Aa Aa Aaa Aaaaaaaaaa Aaaaaa Aaaaaaaa Aaaaaaaa Aaa Aaaaa Aaaaaa Aa Aaaaaaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa a Aaaaaaaaaaaaaaaaaa a Aaaaaaaaa Aaa Aaaaaaaaaaaaa Aaaaaa Aaaaa Aaaa Aaa Aaaaaaa Aaaaaaaa Aa Aaa Aaa Aaaaaa Aaaaaaaaaaa Aaa Aaaaaaaaaaaaa Aaaaa Aaaa Aaaaa Aa a Aaaaaaa Aaaaaa Aaaaaaaa Aaa Aaaaaaaaaaaaaaaa Aaaaaaaa Aaaaaaaaaaa Aaaa Aaaaaaaaaa Aaaaaaaaaaaaa Aaaaaaaaa Aaaaaa Aaa Aaaaaaaaaaa Aaaa Aaaaa Aaaa Aaaaa Aaaaaaaaaaa Aaaa Aaaaa Aa Aaa Aaaaaaaaaaaaaaaaaa Aaaaaaaa
Aaaaaaaa Aaaaaaaaaa Aaaaaaa a Aaaaaaaa Aaaaaa Aaa a Aaaaaaaaa Aaa Aaaaaaaa Aaa Aaaaaa Aaaaaaa Aa Aaaaaa Aaaaa Aaaa Aaa Aaaa Aaaaaaaaaaa Aaa Aaa Aaaaa Aaaa Aaaa Aaaaaaaaaa Aaaaaa Aaaaaaaaaaaa Aa Aaa Aaaaa Aaaa Aa a Aaaaa Aaaaaaaaaa Aaaa Aaaaa Aaaaaaaa Aaaaaaaaaaaaaa Aa Aaa Aaaaaaaaaaaaaaaa Aaaaa Aaaaaaaa Aaaaaaaaaa Aaaaaa Aaaa Aaaa Aaaa Aaaaaaaaaa Aaaaa Aaaaaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaa Aaaaaaaaaaaaa Aaaaaaaa Aa Aaaaaaa Aaaa Aaaaaaa Aaaaaa Aaaa Aaaaaaaaaa Aaaaaaaa
🔒An information-disclosure path through the WebAssembly module loader, including the chain that converts a parser diagnostic into a leaked memory primitive.
Subscribe to read more
Audit directions
a Aaaaaaaaaaaaaaa Aaa Aaaaaaa Aa Aaaaaaaaaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaa Aaaaaaaaaaa Aaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaaaa Aaaa Aaaaaaaa Aaaaaaaaaaaaaa Aa Aaaaa Aaaaaaaaaaaa
a Aaaaaaaaaaaaaaa Aaaaaaaaaaaa Aaaaa Aaaa Aaa Aaaa Aaaaaaaaaaa a Aaaaaa Aaaaa Aaaa Aa Aaaaaa Aaaaaaaaaa Aaaa Aaaaa Aaaaa Aaaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaa Aaaaaa Aaaaaaaaaaa Aaaaaaaaaaa Aaaaaa
a Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaaaa Aaaaa Aaaaaaaaa Aaaaaaa Aaaaaaaaa Aaaaaa Aaaaaaaaaaaaaaaa Aaaaaa Aaa Aaaaa Aaa Aaa Aaaaaa Aaaaaaa Aa Aaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaa
a Aaaaaaaaa Aaaaaaaaaaaa Aaaaaaaa Aaaa Aaaaaaaaaa Aaaaa Aaaaaaaaaaa Aaaa Aaaaaaaaaaaaaa Aaa Aaaaaaaa Aaa Aaa Aaaaa Aaaaaaaa Aaa Aaaaaaaa Aaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaaaaa
🔒Several reusable audit patterns identified across JSC parsers and error formatters, with concrete starting greps for variant discovery.
Subscribe to read more