Bug 313268
| Summary: | FTL operationPopulateObjectInOSR null deref for sunk Int32/Contiguous arrays with holes | ||
|---|---|---|---|
| Product: | WebKit | Reporter: | s96565100 |
| Component: | JavaScriptCore | Assignee: | Shu-yu Guo <syg> |
| Status: | RESOLVED FIXED | ||
| Severity: | Normal | CC: | entryhii, webkit-bug-importer |
| Priority: | P2 | Keywords: | InRadar |
| Version: | WebKit Nightly Build | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
s96565100
The vulnerable logic is located in JavaScriptCore/ftl/FTLOperations.cpp, around lines 110. The 1 day old fix 289a55e3913b covers NaN for double rematerialization but misses the empty JSValue case for Int32/Contiguous sunk arrays. putDirectIndex's debug ASSERT(!value.isCustomGetterSetterSlow()) dereferences null because JSValue() satisfies isCell() (x86_64: asInt64==0 passes !(xyz &NotCellMask)) while asCell() returns null
The stack dump looks like this
JSCell::isCustomGetterSetter(this=0x0) → JSValue::isCustomGetterSetter → JSValue::isCustomGetterSetterSlow → JSObject::putDirectIndex → FTL::operationPopulateObjectInOSR
And the reproduction is as follows
function hot(i) {
let a = new Array(4);
a[0] = 0;
if (i & 1) a[3] = null;
if (i === 500000) Object.defineProperty(Array.prototype, '1', {get() {}, configurable:
true});
if (i & 4) return a;
}
noInline(hot);
for (let i = 0; i < 1500000; i++) hot(i);
the poc crashes at default jsc flags without noInline or any api which is not standard, therefore it is web compatible js. mutation fuzzing (2500 cases) found 15 crashes, all with identical stacks. the common thread is any operation that disturbs an array's shape or prototype. sealing or freezing it, defining properties on length or an index, deleting entries from Array.prototype, adding a getter to Array.prototype, swapping the prototype for a proxy, or pairing Reflect.deleteProperty with a prototype swap. this is a follow up to Bugzilla 312664.
for the fix, same as the landed fix, extended to Int32/Contiguous. when the value is empty, write the hole straight into the butterfly rather than going through putDirectIndex.
else if ((hasInt32(array->indexingType()) || hasContiguous(array->indexingType())) && !value) [[unlikely]]
array->butterfly()->contiguous().atUnsafe(index).setStartingValue(JSValue());
| Attachments | ||
|---|---|---|
| Add attachment proposed patch, testcase, etc. |
Radar WebKit Bug Importer
<rdar://problem/176051382>
Shu-yu Guo
Pull request: https://github.com/WebKit/WebKit/pull/64583
Shu-yu Guo
*** Bug 314521 has been marked as a duplicate of this bug. ***
EWS
Committed 313041@main (d9cbe05de1dc): <https://commits.webkit.org/313041@main>
Reviewed commits have been landed. Closing PR #64583 and removing active labels.