Tuesday, December 26, 2023

qcad does not segfault when qtscript is compiled with -O0.

Hello,

A little over a year ago I reported[1] that qcad started having
segfaults in 7.0 (or 7.1). I thought I would try to debug it today in
7.4 and so enabled DEBUG_PACKAGES and DEBUG variables in the cad/qcad
Makefile and also the x11/qt5/qtscript Makefile hoping to debug the
segfault. In the Makefile for both I set:

DEBUG_PACKAGES= ${BUILD_PACKAGES}
DEBUG= -O0 -g

Then I built the packages, installed them and their debug packages and
hoped to capture a segfault, but it doesn't crash. Apparently enabling
-O0 in qtscript's Makefile makes it not crash. To test that hypothesis,
I commented out the DEBUG line completely and rebuilt qtscript with just
the defaults that DEBUG_PACKAGES inherits and sure enough, after
installing that qtscript package built with -O2 qcad again crashes.

(gdb) bt
#0 0x000003eae2f9a990 in QScriptEnginePrivate::mark (this=0x3eb4af54a80, markStack=...) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/script/api/qscriptengine.cpp:1320
#1 0x000003eae2f14d6c in QTJSC::Heap::markRoots (this=0x3ea8c2129e8) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp:1167
#2 0x000003eae2f13ac5 in QTJSC::Heap::reset (this=0x3ea8c2129e8) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp:1269
#3 QTJSC::Heap::allocate (this=0x3ea8c2129e8, s=<optimized out>) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp:405
#4 0x000003eae2fa3ac2 in QTJSC::JSCell::operator new (size=56, exec=<optimized out>) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h:167
#5 QScriptEnginePrivate::newVariant (this=0x3eb4af54a80, value=...) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/script/api/qscriptengine.cpp:1797
#6 0x000003eae2fa51b5 in QScriptEngine::newVariant (this=<optimized out>, value=...) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/script/api/qscriptengine.cpp:2233
#7 0x000003eade54f63f in qtscript_create_Qt_Axis_class (engine=0x3eaf5f91770, clazz=...) at ../../generated_cpp/com_trolltech_qt_core/qtscript_Qt.cpp:4157
#8 0x000003eade5445ee in qtscript_create_Qt_class (engine=0x3eaf5f91770) at ../../generated_cpp/com_trolltech_qt_core/qtscript_Qt.cpp:8386
#9 0x000003eade62a327 in qtscript_initialize_com_trolltech_qt_core_bindings (extensionObject=...) at ../../generated_cpp/com_trolltech_qt_core/com_trolltech_qt_core_init.cpp:312
#10 0x000003eade3a1d9e in com_trolltech_qt_core_ScriptPlugin::initialize (this=0x3eabb1f6100, key=..., engine=0x3eaf5f91770) at plugin.cpp:21
#11 0x000003eae2fabdf9 in QScriptEngine::importExtension (this=0x3eaf5f91770, extension=...) at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/script/api/qscriptengine.cpp:3769
#12 0x000003ea8abc35ab in RScriptHandlerEcma::RScriptHandlerEcma (this=0x3eabb1e94e0) at RScriptHandlerEcma.cpp:434
#13 0x000003ea8abd4919 in RScriptHandlerEcma::factory () at RScriptHandlerEcma.cpp:1074
#14 0x000003ead8eb2c3e in RScriptHandlerRegistry::createScriptHandler (extension=...) at RScriptHandlerRegistry.cpp:67
#15 0x000003ead8eb2caf in RScriptHandlerRegistry::getGlobalScriptHandler (extension=...) at RScriptHandlerRegistry.cpp:76
#16 0x000003e87ec05021 in main (argc=1, argv=0x7b524ae78618) at main.cpp:389
(gdb) list
1315 }
1316
1317 if (q) {
1318 QScriptContext *context = q->currentContext();
1319
1320 while (context) {
1321 JSC::ScopeChainNode *node = frameForContext(context)->scopeChain();
1322 JSC::ScopeChainIterator it(node);
1323 for (it = node->begin(); it != node->end(); ++it) {
1324 JSC::JSObject *object = *it;

Stepping through with -O2, it seems to go through one or two iterations of a
while loop and then crashes:

(gdb) print context
$8 = (QScriptContext *) 0xf0800cd3288
(gdb) print *context
$9 = {d_ptr = 0x100000000}
(gdb) next
1323 for (it = node->begin(); it != node->end(); ++it) {
(gdb)
1324 JSC::JSObject *object = *it;
(gdb)
1325 if (object)
(gdb)
1326 markStack.append(object);
(gdb)
1323 for (it = node->begin(); it != node->end(); ++it) {
(gdb)
1329 context = context->parentContext();
(gdb)
1320 while (context) {
(gdb) print context
$10 = (QScriptContext *) 0x1
(gdb) next

Thread 1 received signal SIGSEGV, Segmentation fault.
0x00000f07f754b990 in QScriptEnginePrivate::mark (this=0xf079205c480,
markStack=...)
at /usr/ports/pobj/qtscript-5.15.10/qtscript-everywhere-src-5.15.10/src/script/api/qscriptengine.cpp:1320
1320 while (context) {
(gdb) print context
$11 = (QScriptContext *) 0x1

When I run it compiled with -O0 the value of that context pointer is 0x0
at this same moment in execution. Is 0x1 something unique to the
compiler that is trying to protect against bad code?

Is there other useful information that I can try to obtain to figure out
why it's crashing or what it's doing wrong? Is this perhaps a question
for the QCad community?

Thanks,

Andy

[1] https://marc.info/?l=openbsd-misc&m=166019212130315&w=2

No comments:

Post a Comment