hermes icon indicating copy to clipboard operation
hermes copied to clipboard

Too many handles in indirect recursive invocation of stringPrototypeReplace()

Open JimWongM opened this issue 2 years ago • 3 comments

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>)

JimWongM avatar Apr 23 '23 08:04 JimWongM

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.

tmikov avatar Apr 24 '23 01:04 tmikov

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===========

JimWongM avatar May 06 '23 11:05 JimWongM

Confirming, still present.

tmikov avatar Oct 18 '24 17:10 tmikov