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:
parent
c0c35e21b9
commit
d0cb3ae5be
|
@ -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>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue