From a9021009ab295d89e210821693c7f5bd733ccc35 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 28 Apr 2015 18:02:23 +0200 Subject: Fix GC problem with json conversion methods The ObjectSet used to protect against recursion is not safe against a GC that moves objects around. Fix this by storing pointers to QV4::Object in there instead. Change-Id: I88bcac330246a1c9180caed13be1f6ab5c40a6ae Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4jsonobject.cpp | 12 ++++++------ src/qml/jsruntime/qv4jsonobject_p.h | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 652657e1f8..815376c200 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -990,14 +990,14 @@ QJsonObject JsonObject::toJsonObject(const Object *o, V4ObjectSet &visitedObject Scope scope(o->engine()); - if (visitedObjects.contains(o->d())) { + if (visitedObjects.contains(ObjectItem(o))) { // Avoid recursion. // For compatibility with QVariant{List,Map} conversion, we return an // empty object (and no error is thrown). return result; } - visitedObjects.insert(o->d()); + visitedObjects.insert(ObjectItem(o)); ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly); ScopedValue name(scope); @@ -1012,7 +1012,7 @@ QJsonObject JsonObject::toJsonObject(const Object *o, V4ObjectSet &visitedObject result.insert(key, toJsonValue(val, visitedObjects)); } - visitedObjects.remove(o->d()); + visitedObjects.remove(ObjectItem(o)); return result; } @@ -1038,14 +1038,14 @@ QJsonArray JsonObject::toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObj Scope scope(a->engine()); - if (visitedObjects.contains(a->d())) { + if (visitedObjects.contains(ObjectItem(a))) { // Avoid recursion. // For compatibility with QVariant{List,Map} conversion, we return an // empty array (and no error is thrown). return result; } - visitedObjects.insert(a->d()); + visitedObjects.insert(ObjectItem(a)); ScopedValue v(scope); quint32 length = a->getLength(); @@ -1056,7 +1056,7 @@ QJsonArray JsonObject::toJsonArray(const ArrayObject *a, V4ObjectSet &visitedObj result.append(toJsonValue(v, visitedObjects)); } - visitedObjects.remove(a->d()); + visitedObjects.remove(ObjectItem(a)); return result; } diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index dbb49cb592..1ad0e2c5de 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -38,6 +38,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -51,12 +52,23 @@ struct JsonObject : Object { } +struct ObjectItem { + const QV4::Object *o; + ObjectItem(const QV4::Object *o) : o(o) {} +}; + +inline bool operator ==(const ObjectItem &a, const ObjectItem &b) +{ return a.o->d() == b.o->d(); } + +inline int qHash(const ObjectItem &i, uint seed = 0) +{ return ::qHash((void *)i.o->d(), seed); } + struct JsonObject : Object { Q_MANAGED_TYPE(JsonObject) V4_OBJECT2(JsonObject, Object) private: - // ### GC - typedef QSet V4ObjectSet; + + typedef QSet V4ObjectSet; public: static ReturnedValue method_parse(CallContext *ctx); -- cgit v1.2.3