Closed
Bug 345967
Opened 18 years ago
Closed 18 years ago
Yet another unrooted atom in jsarray.c
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
VERIFIED
FIXED
People
(Reporter: igor, Assigned: igor)
Details
(Keywords: verified1.8.0.7, verified1.8.1, Whiteboard: [sg:critical])
Attachments
(2 files, 1 obsolete file)
1.02 KB,
patch
|
mrbkap
:
review+
brendan
:
superreview+
dveditz
:
approval1.8.0.7+
mtschrep
:
approval1.8.1+
|
Details | Diff | Splinter Review |
3.24 KB,
text/plain
|
Details |
The fix for bug 341956 missed the hazard in array_shift. There id for the last element is accessed after changing the element before that. So a setter there can trigger GC which would collect the last id.
Fortunately this is only exploitable on 64bit computer with tens of gigabyte of memory due to bug 345961. Due to that bug a sparse array would be turned into dense one during shift loop. Thus the loop can only start to produce atoms when the array would have at least JSVAL_INT_MAX + 2 or 2^30 + 1 elements. That is not possible to allocate with 32-bit CPU and on 64-bit one just the slot array would take 8GB of memory plus the slot map hashtable overhead.
But if one fixes bug 345961 or if one can find a host object where a setter by default for indexes would do nothing but where one can set object.length to any value, then something like the following can expose the bug after a few minutes:
var JSVAL_INT_MAX = (1 << 30) - 1;
var a = new Array(JSVAL_INT_MAX + 2);
a[JSVAL_INT_MAX] = 0;
a[JSVAL_INT_MAX + 1] = 1;
a.__defineGetter__(JSVAL_INT_MAX, function() { return 0; });
a.__defineSetter__(JSVAL_INT_MAX, function(value) {
delete a[JSVAL_INT_MAX + 1];
var tmp = [];
tmp[JSVAL_INT_MAX + 2] = 2;
if (typeof gc == 'function')
gc();
for (var i = 0; i != 50000; ++i) {
var tmp = 1 / 3;
tmp /= 10;
}
for (var i = 0; i != 1000; ++i) {
// Make string with 11 characters that would take
// (11 + 1) * 2 bytes or sizeof(JSAtom) so eventually
// malloc will ovewrite just freed atoms.
var tmp2 = Array(12).join(' ');
}
});
a.shift();
var expected = 0;
var actual = a[JSVAL_INT_MAX];
if (expected !== actual)
print("BAD");
Assignee | ||
Comment 1•18 years ago
|
||
Given this bug I would *appreciate* if somebody scan jsarray.c one more time for this type of hazards.
Attachment #230727 -
Flags: superreview?(brendan)
Attachment #230727 -
Flags: review?(mrbkap)
Assignee | ||
Comment 2•18 years ago
|
||
This version uses
if (length > JSVAL_INT_MAX && !IndexToId(cx, length, &id))
and not equivalent but bug-looking
if (i > JSVAL_INT_MAX && !IndexToId(cx, length, &id))
Attachment #230727 -
Attachment is obsolete: true
Attachment #230728 -
Flags: superreview?(brendan)
Attachment #230728 -
Flags: review?(mrbkap)
Attachment #230727 -
Flags: superreview?(brendan)
Attachment #230727 -
Flags: review?(mrbkap)
Updated•18 years ago
|
Attachment #230728 -
Flags: review?(mrbkap) → review+
Updated•18 years ago
|
Whiteboard: [sg:critical]
Updated•18 years ago
|
Flags: blocking1.8.1?
Flags: blocking1.8.0.6+
Updated•18 years ago
|
Status: NEW → ASSIGNED
Flags: blocking1.8.1? → blocking1.8.1+
Comment 3•18 years ago
|
||
Comment on attachment 230728 [details] [diff] [review]
Fix v2
sr=me, nominating for branches.
/be
Attachment #230728 -
Flags: superreview?(brendan)
Attachment #230728 -
Flags: superreview+
Attachment #230728 -
Flags: approval1.8.1?
Attachment #230728 -
Flags: approval1.8.0.6?
Assignee | ||
Comment 4•18 years ago
|
||
I committed to the trunk the patch from comment 2.
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Comment 5•18 years ago
|
||
On a 32bit machine, the browser test has repeated out of memory errors on the shift(). Shouldn't the memory error cause the script to terminate?
Updated•18 years ago
|
Flags: in-testsuite+
Assignee | ||
Comment 6•18 years ago
|
||
(In reply to comment #5)
> On a 32bit machine, the browser test has repeated out of memory errors on the
> shift(). Shouldn't the memory error cause the script to terminate?
With the test case this should always happen on 32-bit computer due to bug 345961. On 64-bit one you need 24GB(!) of RAM to finish the test. So this is why the bug is mostly theoretical unless the bug 345961 is fixed.
Comment 7•18 years ago
|
||
(In reply to comment #6)
> (In reply to comment #5)
> > On a 32bit machine, the browser test has repeated out of memory errors on the
> > shift(). Shouldn't the memory error cause the script to terminate?
>
> With the test case this should always happen on 32-bit computer due to bug
> 345961. On 64-bit one you need 24GB(!) of RAM to finish the test. So this is
> why the bug is mostly theoretical unless the bug 345961 is fixed.
But why isn't OOM stopping the script? I don't see a failure to propagate false/null along the way.
/be
Comment 8•18 years ago
|
||
Filed bug 346077 on the out of memory doesn't terminate script issue.
Updated•18 years ago
|
Attachment #230728 -
Flags: approval1.8.1? → approval1.8.1+
Comment 10•18 years ago
|
||
Comment on attachment 230728 [details] [diff] [review]
Fix v2
approved for 1.8.0 branch, a=dveditz for drivers
Attachment #230728 -
Flags: approval1.8.0.7? → approval1.8.0.7+
Assignee | ||
Comment 11•18 years ago
|
||
I committed the patch from comment 2 to MOZILLA_1_8_0_BRANCH
Keywords: fixed1.8.0.7
Comment 12•18 years ago
|
||
Apart from a SIGABRT on macppc opt browser due to out of memory, I see no crashes. Marking verified fixed 1.8.0.7, 1.8, 1.9 20060818 windows/mac*/linux
Status: RESOLVED → VERIFIED
Updated•18 years ago
|
Group: security
Comment 13•18 years ago
|
||
Checking in js1_5/GC/regress-345967.js;
/cvsroot/mozilla/js/tests/js1_5/GC/regress-345967.js,v <-- regress-345967.js
initial revision: 1.1
done
You need to log in
before you can comment on or make changes to this bug.
Description
•