diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-02-15 10:44:54 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-09 10:20:21 +0200 |
commit | e1d3687d64a19d27448b3f8247505daa99261ea1 (patch) | |
tree | 3792e67b42c833a4a8765f952d4d3f2a2fb4fa63 /src/corelib/json/qjsonobject.cpp | |
parent | 9cc106d9d7d951fcf30f4b0f8606afa6b50892ec (diff) |
Fix crashes when creating large documents
Compact an object in regular intervals when inserting
data into it, to avoid the object becoming huge.
Compact an object/array before inserting into another
array or object.
Check that the document doesn't get so big it's overflowing
the internal data structures.
Task-number: QTBUG-29288
Change-Id: Id39d80dac1e7d5a11f40819f41b4b336bce16947
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/json/qjsonobject.cpp')
-rw-r--r-- | src/corelib/json/qjsonobject.cpp | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index 55c736afce..2be9d8891d 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -317,9 +317,10 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue & remove(key); return end(); } + QJsonValue val = value; bool latinOrIntValue; - int valueSize = QJsonPrivate::Value::requiredStorage(value, &latinOrIntValue); + int valueSize = QJsonPrivate::Value::requiredStorage(val, &latinOrIntValue); bool latinKey = QJsonPrivate::useCompressed(key); int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey); @@ -335,16 +336,21 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue & if (keyExists) ++d->compactionCounter; - o->reserveSpace(requiredSize, pos, 1, keyExists); + uint off = o->reserveSpace(requiredSize, pos, 1, keyExists); + if (!off) + return end(); QJsonPrivate::Entry *e = o->entryAt(pos); - e->value.type = value.t; + e->value.type = val.t; e->value.latinKey = latinKey; e->value.latinOrIntValue = latinOrIntValue; - e->value.value = QJsonPrivate::Value::valueToStore(value, (char *)e - (char *)o + valueOffset); + e->value.value = QJsonPrivate::Value::valueToStore(val, (char *)e - (char *)o + valueOffset); QJsonPrivate::copyString((char *)(e + 1), key, latinKey); if (valueSize) - QJsonPrivate::Value::copyData(value, (char *)e + valueOffset, latinOrIntValue); + QJsonPrivate::Value::copyData(val, (char *)e + valueOffset, latinOrIntValue); + + if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) + compact(); return iterator(this, pos); } |