Fatal javascript Out of memory
Reported by
b.kurin...@gmail.com,
Dec 23
|
|||||||
Issue description
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0
Steps to reproduce the problem:
1) ./d8 poc.js
or
2) Open special crafted html-file (based on poc.js) in Google Chrome (poc.html)
poc.js
var vArr = new Array();
function main() {
var ret = new Array(0x20000000);
vArr[1] = ret;
var ret = Array.prototype.sort.call(vArr[6], f2);
vArr[3] = ret;
}
function f1() {
var ret = String.prototype.strike.call(vArr[2], String.fromCharCode(69, 69));
vArr[3] = ret;
}
function f2() {
var ret = f1.apply(vArr[4], vArr[5]); vArr[5] = ret;
for(var index=0; index < 2; index++){
var ret = String.prototype.toLowerCase.call(vArr[1]);
vArr[2] = ret;
}
}
for(var i=0;i<6;i++) {
vArr[i] = new Array();
}
vArr[6] = 'abc';
main();
What is the expected behavior?
execute javascript code
What went wrong?
1) d8 are crashed
2) Tab in Google Chrome are crashed
Did this work before? N/A
Chrome version: 71.0.3578.98 Channel: n/a
OS Version: 10.0
Flash Version:
<--- Last few GCs --->
[5265:0x62e000000400] 2080 ms: Mark-sweep 1536.5 (1539.8) -> 1536.5 (1538.8) MB, 1.3 / 0.0 ms (average mu = 0.945, current mu = 0.014) last resort GC in old space requested
[5265:0x62e000000400] 2081 ms: Mark-sweep 1536.5 (1538.8) -> 1536.5 (1538.8) MB, 1.2 / 0.0 ms (average mu = 0.932, current mu = 0.014) last resort GC in old space requested
<--- JS stacktrace --->
==== JS stack trace =========================================
0: ExitFrame [pc: 0x560ae21d40eb]
1: StubFrame [pc: 0x560ae2204760]
Security context: 0x7e8021f1a101 <JSObject>
2: toLowerCase [0x7e8021f0acc1](this=0x7e8021f260e9 <JSArray[536870912]>)
3: f2 [0x7e8021f24579] [poc.js:32] [bytecode=0x7e8021f24ae9 offset=105](this=0x7e8021f1e179 <JSGlobal Object>)
4: arguments adaptor frame: 2->0
5: StubFrame [pc: 0x560ae21fd4a5]
6: StubFrame [pc: 0x560ae2201499]
7: sort [0x7...
#
# Fatal javascript OOM in CALL_AND_RETRY_LAST
#
Received signal 4 ILL_ILLOPN 560ae235775c
==== C stack trace ===============================
[0x560ae0316e21]
[0x560ae235fdbf]
[0x7f259bf62890]
[0x560ae235775c]
[0x560ae041160d]
[0x560ae041150e]
[0x560ae10c47e9]
[0x560ae10dcd7a]
[0x560ae1054ce0]
[0x560ae15fe314]
[0x560ae19cfa95]
[0x560ae21d40eb]
[end of stack trace]
Illegal instruction (core dumped)
,
Dec 23
Thanks for reporting this! I can reproduce this in canary on mac. Adding component Blink>JavaScript so the V8 team becomes aware of this.
,
Dec 24
Thanks for filing the issue... Able to reproduce the issue on reported chrome version 71.0.3578.98 also on latest chrome 73.0.3649.0 using Mac 10.14.0, Ubuntu 17.10 and Windows 10. Same behavior is seen on M62(62.0.3202.0) hence considering it as non-regression and marking it as Untriaged. Note: Observed blank page on M-60 and M-61-->Uncaught RangeError: Invalid string length Thanks..!
,
Dec 24
Bisected to e8c9649e2570c7e278e70a6584738a3c3f828b2b "[builtins] Increase the maximum string length on 64-bit platforms." Landed in 62.0.3167.0 via r489257 It was reported in bug 791772 which got duped into another hidden issue so it's unclear what the decision was, if any.
,
Dec 24
,
Jan 2
cut-down repro: var vArr = new Array(); var bigArray = new Array(0x20000000); vArr[0] = String.prototype.toLowerCase.call(bigArray); vArr[1] = String.prototype.toLowerCase.call(bigArray); vArr[2] = String.prototype.toLowerCase.call(bigArray);
,
Jan 2
With increased string length we now run into some limit in large object space rather than just failing with a RangeError on string length. Not sure exactly what limit we are hitting here. Lowering priority as this used to be a RangeError anyway. Michi can you take a look? Seems that we fail to allocate a large string in LO space even after last resort GC.
,
Jan 3
The repro creates a 512M array and copies it two times successfully before failing with OOM error. When failing with OOM the live memory is roughly 1.5G which is retained by bigArray and vArr. V8 is unable to allocate another 512M because of the default 2G heap limit. When running with d8 the limit can be increased using `--max-old-space-size=4000` which makes the repro pass. This all looks like working as intended. Loosening string limits does not affect our heap limits.
,
Jan 3
Why is it okay to crash the process instead of throwing an exception which can be processed by the user code? How can the user code detect and prevent this currently? Is there some specification that defines such a hostile approach? Or is it a limit of the V8 architecture? If so, shouldn't it be changed?
,
Jan 3
Similar to Chrome's sandbox, the heap limits guard against malicious code as memory thrashing can take a machine hostile (freeze it). V8 in Chrome has always employed a 2G limit for JS to guard against such attacks. Such limits are opaque to JS. OOM and similar errors are not exposed to JS. Handling would be unintuitive as one could hit an actual OOM (physical limits reached) even earlier in which case the error is always fatal. It's not a limit of V8's architecture and as I already wrote in #8 it can be changed with --max-old-space-size at runtime if needed for non-Chrome environments (or local testing).
,
Jan 3
Previously js code could detect a RangeError exception and show a message to the user or send a beacon to the developer. So it was possible. Also what about OOM inside V8 builtins like bug 918301? It seems obviously possible and very helpful to throw an exception in such cases instead of crashing. The js code could abort its current task, do a clean up, show a meaningful message to the user, keep being functional. Lots of things. The inability to catch an OOM at least when it occurs due to a single huge internal/builtin method invocation keeps JS in the toy land.
,
Jan 3
Error handling around cases that are on the edge of being supported will always be in a grey area unless explicitly defined by some standard. We've improved string handling which is why there's no more RangeError in this exact scenario. Now, you've discovered that using those strings one can run into other limits. The same case (no RangeError but hard OOM) was already reproducible with a different set constants before. We just shifted what's possible a bit. Whether JS and the web should be exposed to resource handling and recovery (memory and OOM) in this case should be answered by language and other standards committees.
,
Jan 4
Spidermonkey when processing this POC throws an exception (allocation size overflow). Why can not do the same in V8?
,
Jan 4
Without knowing what is going on there I suspect that "allocation size overflow" checks whether a specific allocation is allowed wrt to its size. We lifted such restrictions so that this actually works in V8 and the allocations to not fail. What we did not lift is security limits on the sandbox so that more than 2G of memory can be kept at the same time. Throwing an error would allocate and go over said limit. So we either allow bypassing that limit or end up in an infinite loop. That said, these are all implementation details. Whether or not JS should throw on resource errors should be discussed on the appropriate mailing lists. |
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by swarnasree.mukkala@chromium.org
, Dec 23