-
Bug
-
Resolution: Fixed
-
P1: Critical
-
6.7.2, 6.8, 6.9
-
None
-
-
d408caa70 (dev), 479b35519 (6.8), f807ee68b (6.7)
Iterating over a (in fairness buggy) javascript iterator results in infinite C++ recursion and thus segfault when the stack is overflown. Instead of bringing the entire process down, I would expect a RangeError: Maximum call stack size exceeded to the thrown instead (like it is currently case when doing recursion primitively in javascript). The following snippet reproduces the issue when run in a QJSEngine:
// "oldschool" class const C = function() { this.prop = "just here because at least one property is needed"; }; C.prototype = { [Symbol.iterator]() { function *recursiveProcess(obj) { for (const name of Object.getOwnPropertyNames(obj)) { if (typeof obj[Symbol.iterator] === "function") { yield* recursiveProcess(obj); } } } return recursiveProcess(this); }, }; const c = new C(); for (const item of c) { }
The gdb stacktrace looks roughly like this (though it obviously goes thousands of stackframes deep)
#0 0x00007ffff7a1f27b in QV4::ObjectOwnPropertyKeyIterator::next (this=0x44ec50, o=0x7fffe53d9940, pd=0x0, attrs=0x7fffff7ff0a7) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4object.cpp:329 #1 0x00007ffff7a24947 in QV4::ObjectIterator::next (this=0x7fffff7ff140, pd=0x0, attrs=0x7fffff7ff0a7) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4objectiterator.cpp:25 #2 QV4::ObjectIterator::next (this=0x7fffff7ff140, pd=0x0, attrs=0x7fffff7ff0a7) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4objectiterator.cpp:16 #3 0x00007ffff7a24c5b in QV4::ObjectIterator::nextPropertyNameAsString (this=this@entry=0x7fffff7ff140) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4objectiterator.cpp:80 #4 0x00007ffff7a29dcc in QV4::ObjectPrototype::getOwnPropertyNames (v4=v4@entry=0x427670, o=...) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4objectproto.cpp:882 #5 0x00007ffff7a2a13b in QV4::ObjectPrototype::method_getOwnPropertyNames (b=<optimized out>, argv=0x7fffe4573198, argc=<optimized out>) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4objectproto.cpp:179 #6 0x00007ffff7a76888 in QV4::FunctionObject::call (this=<optimized out>, thisObject=0x7fffe45731c0, argv=0x7fffe4573198, argc=1) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4functionobject_p.h:171 #7 QV4::Runtime::CallProperty::call (engine=0x427670, baseRef=<optimized out>, nameIndex=<optimized out>, argv=0x7fffe4573198, argc=1) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4runtime.cpp:1497 #8 0x00007ffff7aad9b6 in QV4::Moth::VME::interpret (frame=0x44ec50, frame@entry=0x7fffe4572fc8, engine=0x427670, code=0x45165a "\326\001\030\b\274G\026\b\330\tE\001\002\n\001\026\t\030\n\032\006\v*\0048\0054\v\344\030\v\022\bl\vP%\036") at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4vme_moth.cpp:321 #9 0x00007ffff79fdc9c in QV4::GeneratorObject::resume (this=<optimized out>, engine=0x427670, arg=...) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:192 #10 0x00007ffff79fdde1 in QV4::GeneratorPrototype::method_next (f=<optimized out>, thisObject=<optimized out>, argv=<optimized out>, argc=<optimized out>) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:134 #11 0x00007ffff7a71ba0 in QV4::FunctionObject::call (this=<optimized out>, thisObject=0x7fffe4572d28, argv=0x7fffe4572cd8, argc=1) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4functionobject_p.h:171 #12 QV4::Runtime::IteratorNextForYieldStar::call (engine=0x427670, received=<optimized out>, iterator=..., object=0x7fffe4572d30) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4runtime.cpp:903 #13 0x00007ffff7aadc99 in QV4::Moth::VME::interpret (frame=0x44ec50, frame@entry=0x7fffe4572b28, engine=0x427670, code=0x451698 "T\367\026\r\030\a\300\001\fV\026\rVL\271\026\bڼ") at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4vme_moth.cpp:748 #14 0x00007ffff79fdc9c in QV4::GeneratorObject::resume (this=<optimized out>, engine=0x427670, arg=...) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:192 #15 0x00007ffff79fdde1 in QV4::GeneratorPrototype::method_next (f=<optimized out>, thisObject=<optimized out>, argv=<optimized out>, argc=<optimized out>) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:134 #16 0x00007ffff7a71ba0 in QV4::FunctionObject::call (this=<optimized out>, thisObject=0x7fffe4572888, argv=0x7fffe4572838, argc=1) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4functionobject_p.h:171 #17 QV4::Runtime::IteratorNextForYieldStar::call (engine=0x427670, received=<optimized out>, iterator=..., object=0x7fffe4572890) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4runtime.cpp:903 #18 0x00007ffff7aadc99 in QV4::Moth::VME::interpret (frame=0x44ec50, frame@entry=0x7fffe4572688, engine=0x427670, code=0x451698 "T\367\026\r\030\a\300\001\fV\026\rVL\271\026\bڼ") at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4vme_moth.cpp:748 #19 0x00007ffff79fdc9c in QV4::GeneratorObject::resume (this=<optimized out>, engine=0x427670, arg=...) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:192 #20 0x00007ffff79fdde1 in QV4::GeneratorPrototype::method_next (f=<optimized out>, thisObject=<optimized out>, argv=<optimized out>, argc=<optimized out>) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:134 #21 0x00007ffff7a71ba0 in QV4::FunctionObject::call (this=<optimized out>, thisObject=0x7fffe45723e8, argv=0x7fffe4572398, argc=1) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4functionobject_p.h:171 #22 QV4::Runtime::IteratorNextForYieldStar::call (engine=0x427670, received=<optimized out>, iterator=..., object=0x7fffe45723f0) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4runtime.cpp:903 #23 0x00007ffff7aadc99 in QV4::Moth::VME::interpret (frame=0x44ec50, frame@entry=0x7fffe45721e8, engine=0x427670, code=0x451698 "T\367\026\r\030\a\300\001\fV\026\rVL\271\026\bڼ") at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4vme_moth.cpp:748 #24 0x00007ffff79fdc9c in QV4::GeneratorObject::resume (this=<optimized out>, engine=0x427670, arg=...) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:192 #25 0x00007ffff79fdde1 in QV4::GeneratorPrototype::method_next (f=<optimized out>, thisObject=<optimized out>, argv=<optimized out>, argc=<optimized out>) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4generatorobject.cpp:134 #26 0x00007ffff7a71ba0 in QV4::FunctionObject::call (this=<optimized out>, thisObject=0x7fffe4571f48, argv=0x7fffe4571ef8, argc=1) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4functionobject_p.h:171 #27 QV4::Runtime::IteratorNextForYieldStar::call (engine=0x427670, received=<optimized out>, iterator=..., object=0x7fffe4571f50) at /usr/src/debug/qt6-qtdeclarative-6.7.2-1.fc40.x86_64/src/qml/jsruntime/qv4runtime.cpp:903
For Gerrit Dashboard: QTBUG-127049 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
579715,6 | QJSEngine: Check for stack overflows on generators | dev | qt/qtdeclarative | Status: MERGED | +2 | +1 |
585756,2 | QJSEngine: Check for stack overflows on generators | 6.8 | qt/qtdeclarative | Status: MERGED | +2 | 0 |
585829,4 | QJSEngine: Check for stack overflows on generators | 6.7 | qt/qtdeclarative | Status: MERGED | +2 | 0 |