QtQml: Check for locals in metatypes stack frame before accessing them

ScopedStackFrame has no locals and we don't want to crash if we manage
to run the GC while e.g. initializing a component.

Amends commmit 2d016a2653

Fixes: QTBUG-140057
Pick-to: 6.10.0 6.10 6.9 6.8
Change-Id: I7aeb39d6cb1f0ca0a661b8cfa2e7c159f968e224
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
This commit is contained in:
Ulf Hermann 2025-09-10 15:00:39 +02:00
parent b3f5cf3b2d
commit 024e43c68f
2 changed files with 20 additions and 7 deletions

View File

@ -1544,13 +1544,13 @@ void MemoryManager::collectFromJSStack(MarkStack *markStack) const
if (!frame->isMetaTypesFrame()) if (!frame->isMetaTypesFrame())
continue; continue;
const QQmlPrivate::AOTTrackedLocalsStorage *locals if (const QQmlPrivate::AOTTrackedLocalsStorage *locals
= static_cast<const MetaTypesStackFrame *>(frame)->locals(); = static_cast<const MetaTypesStackFrame *>(frame)->locals()) {
// Actual AOT-compiled functions initialize the locals firsth thing when they
// locals have to be initialized first thing when calling the function // are called. However, the ScopedStackFrame has no locals, but still uses a
Q_ASSERT(locals); // MetaTypesStackFrame.
locals->markObjects(markStack);
locals->markObjects(markStack); }
} }
} }

View File

@ -65,6 +65,8 @@ private slots:
void scopedConvertToObjectFromReturnedValueDoesNotAccessGarbageOnTheStackOnAllocation(); void scopedConvertToObjectFromReturnedValueDoesNotAccessGarbageOnTheStackOnAllocation();
void scopedConvertToStringFromValueDoesNotAccessGarbageOnTheStackOnAllocation(); void scopedConvertToStringFromValueDoesNotAccessGarbageOnTheStackOnAllocation();
void scopedConvertToObjectFromValueDoesNotAccessGarbageOnTheStackOnAllocation(); void scopedConvertToObjectFromValueDoesNotAccessGarbageOnTheStackOnAllocation();
void dontCrashOnScopedStackFrame();
}; };
tst_qv4mm::tst_qv4mm() tst_qv4mm::tst_qv4mm()
@ -1219,6 +1221,17 @@ void tst_qv4mm::scopedConvertToObjectFromValueDoesNotAccessGarbageOnTheStackOnAl
QV4::ScopedObject object(scope, QV4::StaticValue::fromBoolean(true).asValue<QV4::Value>(), QV4::ScopedObject::Convert); QV4::ScopedObject object(scope, QV4::StaticValue::fromBoolean(true).asValue<QV4::Value>(), QV4::ScopedObject::Convert);
} }
void tst_qv4mm::dontCrashOnScopedStackFrame()
{
QJSEngine jsengine;
QV4::ExecutionEngine *engine = jsengine.handle();
QV4::Scope scope(engine);
QV4::ScopedStackFrame frame(scope, engine->rootContext());
jsengine.collectGarbage();
}
QTEST_MAIN(tst_qv4mm) QTEST_MAIN(tst_qv4mm)
#include "tst_qv4mm.moc" #include "tst_qv4mm.moc"