aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-08-02 11:34:53 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-08-07 22:25:31 +0000
commit13a617610ac7d372316683b3160a2ce6c3eb7af4 (patch)
tree306833452f0e7aeff89dd64400235c1e5a7274e3 /src/qml/jsruntime
parentc5e91abab530909f2dbfa8dc2b0418a8a25bacb1 (diff)
JSON: Properly handle bad objects in JSON.stringify()
For objects with circular structures we generate a proper error message and fail earlier. For objects with excessive recursion we throw a range error rather than crashing. This behavior is modeled after node's behavior in such circumstances. We use the existing stack overflow detection to determine when to throw the range error. Testing shows that on windows the limit was insufficient. Lower it. Fixes: QTBUG-92192 Change-Id: I25dd302f65f359111e42492df3c71549c4ed7157 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> (cherry picked from commit af1ef35fa00a466d3af04c17b59fcb4ea38f396a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp3
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp33
2 files changed, 30 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index a9834200b6..ff85299752 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -364,6 +364,9 @@ void ExecutionEngine::initializeStaticMembers()
#elif defined(Q_OS_ANDROID)
// In experiments, it started crashing at 1059.
s_maxCallDepth = 1000;
+#elif defined(Q_OS_WIN)
+ // We've seen crashes around 750.
+ s_maxCallDepth = 640;
#else
s_maxCallDepth = 1234;
#endif
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 18f9e17f11..130a3ccb23 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -646,6 +646,29 @@ struct Stringify
QString makeMember(const QString &key, const Value &v);
};
+class [[nodiscard]] CallDepthAndCycleChecker
+{
+ Q_DISABLE_COPY_MOVE(CallDepthAndCycleChecker);
+
+public:
+ CallDepthAndCycleChecker(Stringify *stringify, Object *o)
+ : m_callDepthRecorder(stringify->v4)
+ {
+ if (stringify->stackContains(o)) {
+ stringify->v4->throwTypeError(
+ QStringLiteral("Cannot convert circular structure to JSON"));
+ }
+
+ qDebug() << stringify->v4->callDepth;
+ stringify->v4->checkStackLimits();
+ }
+
+ bool foundProblem() const { return m_callDepthRecorder.ee->hasException; }
+
+private:
+ ExecutionEngineCallDepthRecorder m_callDepthRecorder;
+};
+
static QString quote(const QString &str)
{
QString product;
@@ -776,10 +799,9 @@ QString Stringify::makeMember(const QString &key, const Value &v)
QString Stringify::JO(Object *o)
{
- if (stackContains(o)) {
- v4->throwTypeError();
+ CallDepthAndCycleChecker check(this, o);
+ if (check.foundProblem())
return QString();
- }
Scope scope(v4);
@@ -836,10 +858,9 @@ QString Stringify::JO(Object *o)
QString Stringify::JA(Object *a)
{
- if (stackContains(a)) {
- v4->throwTypeError();
+ CallDepthAndCycleChecker check(this, a);
+ if (check.foundProblem())
return QString();
- }
Scope scope(a->engine());