Unsigned integer overflow involving uneval of an array/array.join

RESOLVED INVALID

Status

()

--
critical
RESOLVED INVALID
10 years ago
10 years ago

People

(Reporter: gkw, Assigned: igor)

Tracking

(Blocks: 1 bug, {testcase})

Trunk
x86
Mac OS X
testcase
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

10 years ago
I pushed up jsfunfuzz-running iterations by twice as per normal and hit this bad bug.

x = this;
undefined &=  /x/g ;
undefined -= 1.2e3;
eval("undefined >>>=x");
this.__defineGetter__("x", function ()undefined);
eval("uneval(Array(x));");

eventually causes this in opt js shell with and without "-j":

js-opt-tm-intelmac(37177) malloc: *** mmap(size=2397048832) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
175b.js:6: out of memory

Thanks gal for helping to debug this issue. gal mentions that we seem to be spending "a ton of time in Array.join, we loop over an entire integer range and eventually run OOM." Security-sensitive because it is suspected this is exploitable.

[13:15] gal> (gdb) p length
[13:15] gal> $5 = 4294966096
[13:15] gal> (gdb) p index
[13:15] gal> $6 = 19212946
Flags: blocking1.9.1?

Comment 1

10 years ago
Some scary stuff is happening here. I suggest marking this security critical until we figured out whats going on.

Comment 2

10 years ago
Breakpoint 3, 0x0002a976 in array_join_sub (cx=0x30bbf0, obj=0x291160, op=TO_SOURCE, sep=0x0, rval=0x81424c) at ../jsarray.cpp:1236
1236	               JSString *sep, jsval *rval)
(gdb) n
1247	    JS_CHECK_RECURSION(cx, return JS_FALSE);
(gdb) n
1249	    ok = js_GetLengthProperty(cx, obj, &length);
(gdb) n
1250	    if (!ok)
(gdb) p ok
$9 = 1
(gdb) p length
$10 = 4294966096
(Reporter)

Comment 3

10 years ago
This occurs in 1.9.0.x branch too:

$ ./js-opt-moz190-intelmac 
js> x = this;
[object global]
js> undefined &=  /x/g ;
0
js> undefined -= 1.2e3;
-1200
js> eval("undefined >>>=x");
4294966096
js> this.__defineGetter__("x", function ()undefined);
js> eval("uneval(Array(x));");
js-opt-moz190-intelmac(39329) malloc: *** mmap(size=2397048832) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
typein:6: out of memory
js>
Flags: blocking1.9.0.7?
(Assignee)

Updated

10 years ago
Assignee: general → igor
(Assignee)

Comment 4

10 years ago
In the test case after eval("undefined >>>=x"); the undefined becomes 4294966096. Then the code does Array(x). Since at that point a getter is defined for x that returns undefined, that is equivalent to Array(undefined) or Array(4294966096).

Then the code tries to uneval this array with the length set to 4294966096. For that the code loops constructing a growing buffer that should eventually hold 4294966096 commas. On 32-bit systems that will fail at some point with OOM.

So OOM is the correct behavior here. Note that in a browser or shell with enabled timeout a too slow script will be reported. Thus I mark the bug as invalid.

Note that in principle the code can report an error earlier if it detects that the length of the buffer would exceed the maximum for the JS string length. But that would mean that the getters or toString for some elements of the array would not be called resulting in observable behavior change. So I am not sure that it worth to bother with this.
Status: NEW → RESOLVED
Last Resolved: 10 years ago
Resolution: --- → INVALID
(Assignee)

Updated

10 years ago
Group: core-security

Updated

10 years ago
Flags: blocking1.9.0.7?

Updated

10 years ago
Flags: blocking1.9.1?
You need to log in before you can comment on or make changes to this bug.