diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-11-15 16:26:49 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-11-22 12:32:16 +0100 |
commit | 8f827de1a1cc466f4c99049a90669f1c538e717f (patch) | |
tree | a8d047a5b4e3012bb4d41b4a63e850c41f11aa00 /src/qml/compiler/qv4codegen.cpp | |
parent | cff3977d2ec5e55d0285e13b2bfe31ca04babf66 (diff) | |
download | qtdeclarative-8f827de1a1cc466f4c99049a90669f1c538e717f.tar.gz |
QML: Do not crash on CallWithSpread
We need to check for subscripts also when creating CallWithSpread and
TailCall instructions. Furthermore, the == operator of Reference needs
to take into account whether the subscript has been loaded or not.
Amends commit 872e91612fd83de6dd1193014b5e2a0f5e8c30af.
Fixes: QTBUG-108441
Change-Id: I2d1a7a11f9cdcb4320a87df979d9ca4457620d3f
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Semih Yavuz <semih.yavuz@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 1ce5f9118c..157f831bb8 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1961,6 +1961,7 @@ bool Codegen::visit(CallExpression *ast) break; case Reference::Subscript: base.element = loadSubscriptForCall(base).storeOnStack().stackSlot(); + base.subscriptLoadedForCall = true; break; case Reference::Name: break; @@ -2002,21 +2003,29 @@ bool Codegen::visit(CallExpression *ast) baseObject.storeOnStack(thisObject); baseObject = Reference::fromStackSlot(this, thisObject); } - if (!base.isStackSlot()) { - base.storeOnStack(functionObject); - base = Reference::fromStackSlot(this, functionObject); - } + + const int func = [&]() { + if (base.type == Reference::Subscript) + return base.element; + + if (!base.isStackSlot()) { + base.storeOnStack(functionObject); + base = Reference::fromStackSlot(this, functionObject); + } + + return base.stackSlot(); + }(); if (calldata.hasSpread) { Instruction::CallWithSpread call; - call.func = base.stackSlot(); + call.func = func; call.thisObject = baseObject.stackSlot(); call.argc = calldata.argc; call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } else { Instruction::TailCall call; - call.func = base.stackSlot(); + call.func = func; call.thisObject = baseObject.stackSlot(); call.argc = calldata.argc; call.argv = calldata.argv; @@ -2521,6 +2530,7 @@ bool Codegen::handleTaggedTemplate(Reference base, TaggedTemplate *ast) break; case Reference::Subscript: base.element = loadSubscriptForCall(base).storeOnStack().stackSlot(); + base.subscriptLoadedForCall = true; break; case Reference::Name: break; @@ -4322,7 +4332,9 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const case Member: return propertyBase == other.propertyBase && propertyNameIndex == other.propertyNameIndex; case Subscript: - return elementBase == other.elementBase && elementSubscript == other.elementSubscript; + return elementBase == other.elementBase && other.subscriptLoadedForCall + ? (subscriptLoadedForCall && element == other.element) + : (!subscriptLoadedForCall && elementSubscript == other.elementSubscript); case Import: return index == other.index; case Const: |