Too many handles in indirect recursive invocation of stringPrototypeReplace()
Bug Description
Hermes crash when I run test.js below. The code in try...catch... will throw a rangeError: Maximum call stack size exceed. Hermes should print the exception instead of crashing.
StackTrace:
hermes: /home/wjm/hermes_validate/hermes/include/hermes/VM/HandleRootOwner.h:443: hermes::vm::PinnedHermesValue* hermes::vm::GCScope::newPinnedHermesValue(hermes::vm::HermesValue): Assertion `getHandleCountDbg() < handlesLimit_ && "Too many handles allocated in GCScope"' failed.
Hermes version: ab9110de7d37375982785ef674d86679093831cd React Native version (if any): OS version (if any): Platform: x86_64
Steps To Reproduce
Hermes should be compiled in Debug mode.
./hermes test.js
code example:
function main(){
function F0(a2, a3, a4) {
try{
if (!new.target) { throw 'must be called with new'; }
const v6 = ("kAvR").replace;
function f7() {
return v6;
}
Object.defineProperty(v6, Symbol.toPrimitive, { enumerable: true, get: f7 });
f7 >>>= v6;
}
catch(e)
{
print(e)
}
}
const v10 = new F0();
}; main();
The Expected Behavior
I test the code in V8. V8 prints the stacktrace and does not crash.
RangeError: Maximum call stack size exceeded
at Function.f7 (<anonymous>:7:13)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
at Function.replace (<anonymous>)
Thank you for reporting this! We will address it.
Please note that it isn't a production bug, because this assert() is just a heuristic way to ensure in debug mode that we manage resources efficiently by not allocating too many handles. Allocating many handles in itself is not a necessarily problem, the handles are not leaked and they are very cheap, so it is just a potential small inefficiency.
In this case the number of handles allocated is proportional to the depth of the stack, which is not a problem, so the heuristic is failing.
Still, it must be fixed, otherwise the heuristic becomes useless.
Hello, I notice StringPrototypeTrimStart/StringProtypeToLowerCase also has the same problem. code example: ===========test.js================= const v6 = ("test").trimStart; //toLowercase function f7() { return v6; } Object.defineProperty(v6, Symbol.toPrimitive, { get: f7 }); f7 >>>= v6; ============end of test.js===========
Confirming, still present.