QJSEngine: Fix potential JS stack overflow cauased by spread operator

createSpreadArguments could in theory allocate a (nearly) unbounded
number of QV4::Values. Avoid this by checking whether we approach
jsStackTop.

This fixes CVE-2022-43591.

Change-Id: I01aecb979da47b7261688c9f185dc33a50a579a5
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit 6511aa4344)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Fabian Kosmale 2023-01-19 10:56:50 +01:00 committed by Qt Cherry-pick Bot
parent c0c35e21b9
commit d0cb3ae5be
2 changed files with 16 additions and 0 deletions

View File

@ -1539,6 +1539,11 @@ static CallArgs createSpreadArguments(Scope &scope, Value *argv, int argc)
if (done->booleanValue())
break;
++argCount;
constexpr auto safetyMargin = 100; // leave some space on the stack for actual work with the elements
if (qint64(scope.engine->jsStackLimit - scope.engine->jsStackTop) < safetyMargin) {
scope.engine->throwRangeError(QLatin1String("Too many elements in array to use it with the spread operator"));
return { nullptr, 0 };
}
v = scope.alloc<Scope::Uninitialized>();
}
}

View File

@ -274,6 +274,7 @@ private slots:
void coerceValue();
void callWithSpreadOnElement();
void spreadNoOverflow();
public:
Q_INVOKABLE QJSValue throwingCppMethod1();
@ -5859,6 +5860,16 @@ void tst_QJSEngine::callWithSpreadOnElement()
QVERIFY(!result.isError());
}
void tst_QJSEngine::spreadNoOverflow()
{
QJSEngine engine;
const QString program = QString::fromLatin1("var a = [] ;a.length = 555840;Math.max(...a)");
const QJSValue result = engine.evaluate(program);
QVERIFY(result.isError());
QCOMPARE(result.errorType(), QJSValue::RangeError);
}
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"