QJsonDocument: Avoid overflow of string lengths
The added test case contains the binary JSON equivalent of ["ž"] with the modification that the string's length has been set to INT_MAX. In Value::usedStorage this length is used through the pointer d like so s = sizeof(int) + sizeof(ushort) * qFromLittleEndian(*(int *)d); Because 2 * INT_MAX is UINT_MAX-1, the expression as a whole evaluates to 2, which is considered a valid storage size. However, when converting this binary JSON into ordinary JSON we will attempt to construct a QString of length INT_MAX. Fixed by using String::isValid instead of Value::usedStorage. This method already takes care to avoid the overflow problem. Additionally, I've tried in this patch to clarify the behavior of Value::isValid a bit by writing it in a style that is hopefully more amenable to structural induction. Finally, the test case added in my previous patch had the wrong file extension and is renamed in this one. Task-number: QTBUG-61969 Change-Id: I45d891f2467a71d8d105822ef7eb1a73c3efa67a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
bff2101994
commit
8e47474baf
@ -326,38 +326,35 @@ int Value::usedStorage(const Base *b) const
|
||||
return alignedSize(s);
|
||||
}
|
||||
|
||||
inline bool isValidValueOffset(uint offset, uint tableOffset)
|
||||
{
|
||||
return offset >= sizeof(Base)
|
||||
&& offset + sizeof(uint) <= tableOffset;
|
||||
}
|
||||
|
||||
bool Value::isValid(const Base *b) const
|
||||
{
|
||||
int offset = -1;
|
||||
switch (type) {
|
||||
case QJsonValue::Double:
|
||||
if (latinOrIntValue)
|
||||
break;
|
||||
Q_FALLTHROUGH();
|
||||
case QJsonValue::String:
|
||||
case QJsonValue::Array:
|
||||
case QJsonValue::Object:
|
||||
offset = value;
|
||||
break;
|
||||
case QJsonValue::Null:
|
||||
case QJsonValue::Bool:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (offset == -1)
|
||||
return true;
|
||||
if (offset + sizeof(uint) > b->tableOffset || offset < (int)sizeof(Base))
|
||||
case QJsonValue::Double:
|
||||
return latinOrIntValue || isValidValueOffset(value, b->tableOffset);
|
||||
case QJsonValue::String:
|
||||
if (!isValidValueOffset(value, b->tableOffset))
|
||||
return false;
|
||||
if (latinOrIntValue)
|
||||
return asLatin1String(b).isValid(b->tableOffset - value);
|
||||
return asString(b).isValid(b->tableOffset - value);
|
||||
case QJsonValue::Array:
|
||||
return isValidValueOffset(value, b->tableOffset)
|
||||
&& static_cast<Array *>(base(b))->isValid(b->tableOffset - value);
|
||||
case QJsonValue::Object:
|
||||
return isValidValueOffset(value, b->tableOffset)
|
||||
&& static_cast<Object *>(base(b))->isValid(b->tableOffset - value);
|
||||
default:
|
||||
return false;
|
||||
|
||||
int s = usedStorage(b);
|
||||
if (s < 0 || s > (int)b->tableOffset - offset)
|
||||
return false;
|
||||
if (type == QJsonValue::Array)
|
||||
return static_cast<Array *>(base(b))->isValid(s);
|
||||
if (type == QJsonValue::Object)
|
||||
return static_cast<Object *>(base(b))->isValid(s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
BIN
tests/auto/corelib/serialization/json/invalidBinaryData/41.bjson
Normal file
BIN
tests/auto/corelib/serialization/json/invalidBinaryData/41.bjson
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user