A bug in toUpperCase string chars reallocation
Categories
(Core :: JavaScript Engine, defect)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox-esr115 | --- | unaffected |
| firefox-esr128 | --- | unaffected |
| firefox135 | --- | wontfix |
| firefox136 | + | fixed |
| firefox137 | + | fixed |
People
(Reporter: anbu1024.me, Assigned: jandem)
References
(Regression)
Details
(4 keywords, Whiteboard: [adv-main136+])
Attachments
(3 files)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0
Steps to reproduce:
A bug in JIT optimization, whether there are security risks or not requires further in-depth analysis.
version:commit 3166120f85161b7fe84565135b04c685da1dd34f
Build options:
/bin/sh ../../gecko-dev/js/src/configure --enable-debug --disable-optimize --disable-shared-js --disable-tests --enable-gczeal
Test case:
./js --baseline-warmup-threshold=10 --ion-warmup-threshold=50 --ion-check-range-analysis --ion-extra-checks
case1:
function opt(){
const v0 = String.fromCharCode(-1896350971);
const v1 = Number();
const v2 = [v1,-128,v0];
const v3 = JSON.stringify(v2);
const v4 = String.fromCharCode();
const v5 = eval();
async function v6() {
const v7 = await "";
}
const v8 = v6();
const v9 = v4.padEnd(46985);
const v10 = v9.replace(v4);
const v11 = v3.toUpperCase();
return v11;
}
let a = opt();
let b = opt();
for (let i = 0; i < 55; i++) {
opt();
}
let c = opt();
print(a);
print(b);
print(c);
case2:
function opt(){
function v0() {
let v1 = 1024;
async function v2() {
await "";
}
v2();
const v3 = [];
const v4 = v1--;
v3.length = v4;
const v5 = v3.toLocaleString();
const v6 = eval();
}
v0();
v0();
const v7 = [2282168226];
const v8 = v7 + v7;
const v9 = "valueOf".includes();
const v10 = String.fromCharCode(v9,2282168226,v8,v7);
const v11 = JSON.stringify(v10);
const v12 = v11.toUpperCase();
return v12;
}
let a = opt();
let b = opt();
for (let i = 0; i < 55; i++) {
opt();
}
let c = opt();
print(a);
print(b);
print(c);
case3:
function opt(){
const v0 = [2282168226];
const v1 = v0 + v0;
const v2 = new WeakMap();
const v3 = [1e-15,[],Proxy];
const v4 = new Proxy([],v2);
for (const v5 in v3) {
v4[1000] >>= v5;
let v6 = 1024;
const v7 = [];
const v8 = v6--;
v7.length = v8;
const v9 = v7.toLocaleString();
function v10() {
}
const v11 = new Promise(Promise);
const v12 = v11.catch(v10);
const v13 = eval();
}
const v14 = new Uint16Array();
const v15 = "valueOf".includes();
const v16 = String.fromCharCode(v15,2282168226,v1,v0);
const v17 = JSON.stringify(v16);
const v18 = v17.toUpperCase();
return v18;
}
let a = opt();
let b = opt();
for (let i = 0; i < 55; i++) {
opt();
}
let c = opt();
print(JSON.stringify(a));
print(JSON.stringify(b));
print(JSON.stringify(c));
Actual results:
The result has changed after JIT optimization.
case1:
a = [0,-12ⴭ<ⴭST"]
b = [0,-12ⴭ<ⴭST"]
c = [0,-12
case2:
a = "\U000ⴭὪΙ怀ὪΙ"
b = "\U000ⴭὪΙ怀ὪΙ"
c = "\U000
case3:
a = "\"\\U000ⴭὪΙ怀ὪΙ\""
b = "\"\\U000ⴭὪΙ怀ὪΙ\""
c = "\"\\U000\u0000ὪΙ怀ὪΙ\""
Updated•10 months ago
|
Updated•10 months ago
|
| Assignee | ||
Comment 1•10 months ago
|
||
I'm looking into this. Likely a problem with toUpperCase.
| Assignee | ||
Comment 2•10 months ago
|
||
This is a nice catch. Here's a minimal test case:
assertEq("...........\u1FA2".toUpperCase(), "...........\u1F6A\u0399");
This fails with:
Error: Assertion failed: got "......\u2D2D\uFFFE\u2D2D\u2D2D\u2D2D\u1F6A\u0399", expected "...........\u1F6A\u0399"
Note that 0x2D is a poison value. The original test is more complicated, to end up with different values for the uninitialized/poison bytes that then fail the check.
This happens because in StringChars<CharT>::maybeRealloc we do a memcpy that copies InlineLength bytes from the inline storage to a nursery-allocated buffer, instead of InlineLength * sizeof(CharT) bytes. This affects strings like this case where the upper-case version is longer than the original string.
I'll mark this sec-moderate because this could be used to read (a small number of) uninitialized nursery memory bytes.
| Assignee | ||
Comment 3•10 months ago
|
||
| Assignee | ||
Comment 4•10 months ago
|
||
| Assignee | ||
Updated•10 months ago
|
Comment 5•10 months ago
|
||
Set release status flags based on info from the regressing bug 1910084
Updated•10 months ago
|
Updated•10 months ago
|
| Assignee | ||
Comment 7•10 months ago
|
||
Comment on attachment 9465641 [details]
Bug 1947139 - Fix memcpy in StringChars::maybeRealloc. r?iain!
Beta/Release Uplift Approval Request
- User impact if declined/Reason for urgency: Security issues, broken websites.
- Is this code covered by automated tests?: Yes
- Has the fix been verified in Nightly?: No
- Needs manual test from QE?: No
- If yes, steps to reproduce:
- List of other uplifts needed: None
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): It's a very small and straight-forward patch.
- String changes made/needed: N/A
- Is Android affected?: Yes
Updated•10 months ago
|
Comment 8•10 months ago
|
||
Comment 9•10 months ago
|
||
Comment on attachment 9465641 [details]
Bug 1947139 - Fix memcpy in StringChars::maybeRealloc. r?iain!
Approved for 136.0b7
Comment 10•10 months ago
|
||
| uplift | ||
Updated•10 months ago
|
Updated•10 months ago
|
Updated•9 months ago
|
Comment 11•9 months ago
|
||
Updated•9 months ago
|
Comment 12•7 months ago
|
||
Comment 13•7 months ago
|
||
Updated•5 months ago
|
Description
•