diff options
author | Lars Knoll <lars.knoll@theqtcompany.com> | 2015-03-18 08:49:39 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2016-02-18 07:38:28 +0000 |
commit | 03f1a69e9cffe919597373471f7609521a465470 (patch) | |
tree | 83953ccc59c058dfa66b44e32f51dac5ade9c953 /src/corelib/json/qjsonobject.cpp | |
parent | 6342fb2c3ec516eb5f0fcbd883a65e61acc802de (diff) |
Avoid size overflows when inserting into very large JSON objects
QJson has a size limitation for arrays and objects. Make sure we
don't go over that size limit and create corrupt objects when
inserting data.
Change-Id: I45be3caefc282d8041f38acd120b985ed4389b8c
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/json/qjsonobject.cpp')
-rw-r--r-- | src/corelib/json/qjsonobject.cpp | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index e43d811157..8b45dd196b 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -389,7 +389,8 @@ QJsonObject::iterator QJsonObject::insert(const QString &key, const QJsonValue & int valueOffset = sizeof(QJsonPrivate::Entry) + QJsonPrivate::qStringSize(key, latinKey); int requiredSize = valueOffset + valueSize; - detach(requiredSize + sizeof(QJsonPrivate::offset)); // offset for the new index entry + if (!detach2(requiredSize + sizeof(QJsonPrivate::offset))) // offset for the new index entry + return iterator(); if (!o->length) o->tableOffset = sizeof(QJsonPrivate::Object); @@ -433,7 +434,7 @@ void QJsonObject::remove(const QString &key) if (!keyExists) return; - detach(); + detach2(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) @@ -460,7 +461,7 @@ QJsonValue QJsonObject::take(const QString &key) return QJsonValue(QJsonValue::Undefined); QJsonValue v(d, o, o->entryAt(index)->value); - detach(); + detach2(); o->removeItems(index, 1); ++d->compactionCounter; if (d->compactionCounter > 32u && d->compactionCounter >= unsigned(o->length) / 2u) @@ -554,7 +555,7 @@ QJsonObject::iterator QJsonObject::find(const QString &key) int index = o ? o->indexOf(key, &keyExists) : 0; if (!keyExists) return end(); - detach(); + detach2(); return iterator(this, index); } @@ -1061,21 +1062,35 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const */ void QJsonObject::detach(uint reserve) { + Q_UNUSED(reserve) + Q_ASSERT(!reserve); + detach2(reserve); +} + +bool QJsonObject::detach2(uint reserve) +{ if (!d) { + if (reserve >= QJsonPrivate::Value::MaxSize) { + qWarning("QJson: Document too large to store in data structure"); + return false; + } d = new QJsonPrivate::Data(reserve, QJsonValue::Object); o = static_cast<QJsonPrivate::Object *>(d->header->root()); d->ref.ref(); - return; + return true; } if (reserve == 0 && d->ref.load() == 1) - return; + return true; QJsonPrivate::Data *x = d->clone(o, reserve); + if (!x) + return false; x->ref.ref(); if (!d->ref.deref()) delete d; d = x; o = static_cast<QJsonPrivate::Object *>(d->header->root()); + return true; } /*! @@ -1086,7 +1101,7 @@ void QJsonObject::compact() if (!d || !d->compactionCounter) return; - detach(); + detach2(); d->compact(); o = static_cast<QJsonPrivate::Object *>(d->header->root()); } |