aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-03-01 14:57:21 +0100
committerUlf Hermann <ulf.hermann@qt.io>2019-03-04 15:07:41 +0000
commit783ec60774a565f3a16c25af076b720de0e6acbd (patch)
tree5a55f300ffb15ebf825c5afdb61a2abcfe7bbc8b
parent073977a7a1e79d0cf4ebeaa044045986f29c1d04 (diff)
Disable tail calls for function called with more arguments than formals
We cannot easily find the required stack space to store the extra arguments without adding a new stack frame. In principle it would be possible, but heavily recursing on such functions should be a rare problem. Change-Id: I1a53a6d29e37ce67aa7bd64acb7b1f41197e84c0 Fixes: QTBUG-72807 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp4
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp13
2 files changed, 16 insertions, 1 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 424103cb08..53dd3a66dd 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1561,12 +1561,14 @@ ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *en
const Value &thisObject = tos[StackOffsets::tailCall_thisObject];
Value *argv = reinterpret_cast<Value *>(frame->jsFrame) + tos[StackOffsets::tailCall_argv].int_32();
int argc = tos[StackOffsets::tailCall_argc].int_32();
+ Q_ASSERT(argc >= 0);
if (!function.isFunctionObject())
return engine->throwTypeError();
const FunctionObject &fo = static_cast<const FunctionObject &>(function);
- if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger()) {
+ if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger()
+ || unsigned(argc) > fo.formalParameterCount()) {
// Cannot tailcall, do a normal call:
return fo.call(&thisObject, argv, argc);
}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index f849403cd8..eb9b05e764 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -363,6 +363,7 @@ private slots:
void templateStringTerminator();
void arrayAndException();
void numberToStringWithRadix();
+ void tailCallWithArguments();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -8894,6 +8895,18 @@ void tst_qqmlecmascript::numberToStringWithRadix()
}
}
+void tst_qqmlecmascript::tailCallWithArguments()
+{
+ QJSEngine engine;
+ const QJSValue value = engine.evaluate(
+ "'use strict';\n"
+ "[[1, 2]].map(function (a) {\n"
+ " return (function() { return Math.min.apply(this, arguments); })(a[0], a[1]);\n"
+ "})[0];");
+ QVERIFY(!value.isError());
+ QCOMPARE(value.toInt(), 1);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"