🐛 fix for #962

Added out_of_range exception for UBJSON containers with sizes that exceed the target container's max_size.
pull/957/head
Niels Lohmann 2018-02-06 22:38:53 +01:00
parent 8b457ace25
commit 33a9b00ce6
No known key found for this signature in database
GPG Key ID: 7F3CEA63AE251B69
5 changed files with 53 additions and 6 deletions

View File

@ -263,6 +263,7 @@ json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. |
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
@liveexample{The following code shows how an `out_of_range` exception can be
caught.,out_of_range}

View File

@ -1246,14 +1246,22 @@ class binary_reader
if (size_and_type.first != string_t::npos)
{
if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(size_and_type.first)));
}
if (size_and_type.second != 0)
{
if (size_and_type.second != 'N')
{
std::generate_n(std::back_inserter(*result.m_value.array),
size_and_type.first, [this, size_and_type]()
{
return get_ubjson_value(size_and_type.second);
});
{
return get_ubjson_value(size_and_type.second);
});
}
}
else
{
@ -1283,6 +1291,12 @@ class binary_reader
if (size_and_type.first != string_t::npos)
{
if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(size_and_type.first)));
}
if (size_and_type.second != 0)
{
std::generate_n(std::inserter(*result.m_value.object,

View File

@ -756,6 +756,7 @@ json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference
json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON only supports integers numbers up to 9223372036854775807. |
json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
@liveexample{The following code shows how an `out_of_range` exception can be
caught.,out_of_range}
@ -6066,14 +6067,22 @@ class binary_reader
if (size_and_type.first != string_t::npos)
{
if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(size_and_type.first)));
}
if (size_and_type.second != 0)
{
if (size_and_type.second != 'N')
{
std::generate_n(std::back_inserter(*result.m_value.array),
size_and_type.first, [this, size_and_type]()
{
return get_ubjson_value(size_and_type.second);
});
{
return get_ubjson_value(size_and_type.second);
});
}
}
else
{
@ -6103,6 +6112,12 @@ class binary_reader
if (size_and_type.first != string_t::npos)
{
if (JSON_UNLIKELY(size_and_type.first > result.max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(size_and_type.first)));
}
if (size_and_type.second != 0)
{
std::generate_n(std::inserter(*result.m_value.object,

View File

@ -58,6 +58,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
// type errors can occur during parsing, too
}
catch (const json::out_of_range&)
{
// out of range errors may happen if provided sizes are excessive
}
// return 0 - non-zero return values are reserved for future use
return 0;

View File

@ -1423,4 +1423,17 @@ TEST_CASE("regression tests")
json j = json::from_cbor(v_cbor);
CHECK(j == "abcd123");
}
SECTION("issue #962 - Timeout (OSS-Fuzz 6034)")
{
std::vector<uint8_t> v_ubjson = {0x5b, 0x24, 0x5a, 0x23, 0x4c, 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17};
CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
"[json.exception.out_of_range.408] excessive array size: 8658170730974374167");
v_ubjson[0] = '{';
CHECK_THROWS_AS(json::from_ubjson(v_ubjson), json::out_of_range&);
CHECK_THROWS_WITH(json::from_ubjson(v_ubjson),
"[json.exception.out_of_range.408] excessive object size: 8658170730974374167");
}
}