🔨 changed an exception

This commit is contained in:
Niels Lohmann 2017-03-08 18:07:21 +01:00
parent 8fcd01631f
commit fc9b528ec9
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
6 changed files with 106 additions and 77 deletions

View file

@ -7374,10 +7374,11 @@ class basic_json
template<typename T>
static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
{
if (current_index + sizeof(T) + 1 > vec.size())
{
JSON_THROW(parse_error(110, current_index + 1, "cannot read " + std::to_string(sizeof(T)) + " bytes from vector"));
}
check_length(vec.size(), sizeof(T), current_index + 1);
//if (current_index + sizeof(T) + 1 > vec.size())
//{
// JSON_THROW(parse_error(110, current_index + 1, "cannot read " + std::to_string(sizeof(T)) + " bytes from vector"));
//}
T result;
auto* ptr = reinterpret_cast<uint8_t*>(&result);
@ -7926,19 +7927,19 @@ class basic_json
// simple case: requested length is greater than the vector's length
if (len > size or offset > size)
{
JSON_THROW(std::out_of_range("len out of range"));
JSON_THROW(parse_error(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
}
// second case: adding offset would result in overflow
if ((size > (std::numeric_limits<size_t>::max() - offset)))
{
JSON_THROW(std::out_of_range("len+offset out of range"));
JSON_THROW(parse_error(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
}
// last case: reading past the end of the vector
if (len + offset > size)
{
JSON_THROW(std::out_of_range("len+offset out of range"));
JSON_THROW(parse_error(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
}
}

View file

@ -7374,10 +7374,8 @@ class basic_json
template<typename T>
static T get_from_vector(const std::vector<uint8_t>& vec, const size_t current_index)
{
if (current_index + sizeof(T) + 1 > vec.size())
{
JSON_THROW(parse_error(110, current_index + 1, "cannot read " + std::to_string(sizeof(T)) + " bytes from vector"));
}
// check if we can read sizeof(T) bytes starting the next index
check_length(vec.size(), sizeof(T), current_index + 1);
T result;
auto* ptr = reinterpret_cast<uint8_t*>(&result);
@ -7926,19 +7924,19 @@ class basic_json
// simple case: requested length is greater than the vector's length
if (len > size or offset > size)
{
JSON_THROW(std::out_of_range("len out of range"));
JSON_THROW(parse_error(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
}
// second case: adding offset would result in overflow
if ((size > (std::numeric_limits<size_t>::max() - offset)))
{
JSON_THROW(std::out_of_range("len+offset out of range"));
JSON_THROW(parse_error(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
}
// last case: reading past the end of the vector
if (len + offset > size)
{
JSON_THROW(std::out_of_range("len+offset out of range"));
JSON_THROW(parse_error(110, offset + 1, "cannot read " + std::to_string(len) + " bytes from vector"));
}
}

View file

@ -49,13 +49,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
// serializations must match
assert(s1 == s2);
}
catch (const std::invalid_argument&)
catch (const json::parse_error&)
{
// parsing a JSON serialization must not fail
assert(false);
}
}
catch (const std::invalid_argument&)
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}

View file

@ -1162,35 +1162,35 @@ TEST_CASE("CBOR")
CHECK_THROWS_AS(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x18})),
"[json.exception.parse_error.110] parse error at 1: cannot read 1 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 1 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x19})),
"[json.exception.parse_error.110] parse error at 1: cannot read 2 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 2 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x19, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 2 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 2 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1a, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_cbor(std::vector<uint8_t>({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
}
SECTION("unsupported bytes")
@ -1341,21 +1341,13 @@ TEST_CASE("CBOR regressions", "[!throws]")
// deserializations must match
CHECK(j1 == j2);
}
catch (const std::invalid_argument&)
catch (const json::parse_error&)
{
// parsing a CBOR serialization must not fail
CHECK(false);
}
}
catch (const std::invalid_argument&)
{
// parse errors are ok, because input may be random bytes
}
catch (const std::out_of_range&)
{
// parse errors are ok, because input may be random bytes
}
catch (const std::domain_error&)
catch (const json::parse_error&)
{
// parse errors are ok, because input may be random bytes
}
@ -1365,7 +1357,9 @@ TEST_CASE("CBOR regressions", "[!throws]")
SECTION("improve code coverage")
{
// exotic edge case
CHECK_THROWS_AS(json::check_length(0xffffffffffffffffull, 0xfffffffffffffff0ull, 0xff), std::out_of_range);
CHECK_THROWS_AS(json::check_length(0xffffffffffffffffull, 0xfffffffffffffff0ull, 0xff), json::parse_error);
CHECK_THROWS_WITH(json::check_length(0xffffffffffffffffull, 0xfffffffffffffff0ull, 0xff),
"[json.exception.parse_error.110] parse error at 256: cannot read 18446744073709551600 bytes from vector");
}
}

View file

@ -1038,35 +1038,35 @@ TEST_CASE("MessagePack")
CHECK_THROWS_AS(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcc})),
"[json.exception.parse_error.110] parse error at 1: cannot read 1 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 1 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcd})),
"[json.exception.parse_error.110] parse error at 1: cannot read 2 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 2 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcd, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 2 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 2 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xce, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 4 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
CHECK_THROWS_WITH(json::from_msgpack(std::vector<uint8_t>({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
"[json.exception.parse_error.110] parse error at 1: cannot read 8 bytes from vector");
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
}
SECTION("unsupported bytes")

View file

@ -613,37 +613,51 @@ TEST_CASE("regression tests")
{
// original test case
std::vector<uint8_t> vec {0x65, 0xf5, 0x0a, 0x48, 0x21};
CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec),
"[json.exception.parse_error.110] parse error at 2: cannot read 5 bytes from vector");
}
SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)")
{
// original test case: incomplete float64
std::vector<uint8_t> vec1 {0xcb, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_msgpack(vec1), std::out_of_range);
CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(vec1),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
// related test case: incomplete float32
std::vector<uint8_t> vec2 {0xca, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_msgpack(vec2), std::out_of_range);
CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(vec2),
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
// related test case: incomplete Half-Precision Float (CBOR)
std::vector<uint8_t> vec3 {0xf9, 0x8f};
CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec3),
"[json.exception.parse_error.110] parse error at 2: cannot read 2 bytes from vector");
// related test case: incomplete Single-Precision Float (CBOR)
std::vector<uint8_t> vec4 {0xfa, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_cbor(vec4), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec4), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec4),
"[json.exception.parse_error.110] parse error at 2: cannot read 4 bytes from vector");
// related test case: incomplete Double-Precision Float (CBOR)
std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a};
CHECK_THROWS_AS(json::from_cbor(vec5), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec5), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec5),
"[json.exception.parse_error.110] parse error at 2: cannot read 8 bytes from vector");
}
SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)")
{
// original test case
std::vector<uint8_t> vec1 {0x87};
CHECK_THROWS_AS(json::from_msgpack(vec1), std::out_of_range);
CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(vec1),
"[json.exception.parse_error.110] parse error at 2: cannot read 1 bytes from vector");
// more test cases for MessagePack
for (auto b :
@ -655,7 +669,7 @@ TEST_CASE("regression tests")
})
{
std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
CHECK_THROWS_AS(json::from_msgpack(vec), std::out_of_range);
CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error);
}
// more test cases for CBOR
@ -670,28 +684,38 @@ TEST_CASE("regression tests")
})
{
std::vector<uint8_t> vec(1, static_cast<uint8_t>(b));
CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error);
}
// special case: empty input
std::vector<uint8_t> vec2;
CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range);
CHECK_THROWS_AS(json::from_msgpack(vec2), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec2),
"[json.exception.parse_error.110] parse error at 1: cannot read 1 bytes from vector");
CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error);
CHECK_THROWS_WITH(json::from_msgpack(vec2),
"[json.exception.parse_error.110] parse error at 1: cannot read 1 bytes from vector");
}
SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)")
{
// original test case: empty UTF-8 string (indefinite length)
std::vector<uint8_t> vec1 {0x7f};
CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec1),
"[json.exception.parse_error.110] parse error at 2: cannot read 1 bytes from vector");
// related test case: empty array (indefinite length)
std::vector<uint8_t> vec2 {0x9f};
CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec2),
"[json.exception.parse_error.110] parse error at 2: cannot read 1 bytes from vector");
// related test case: empty map (indefinite length)
std::vector<uint8_t> vec3 {0xbf};
CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec3),
"[json.exception.parse_error.110] parse error at 2: cannot read 1 bytes from vector");
}
SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)")
@ -717,19 +741,27 @@ TEST_CASE("regression tests")
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60
};
CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec),
"[json.exception.parse_error.110] parse error at 137: cannot read 1 bytes from vector");
// related test case: nonempty UTF-8 string (indefinite length)
std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61};
CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec1),
"[json.exception.parse_error.110] parse error at 4: cannot read 1 bytes from vector");
// related test case: nonempty array (indefinite length)
std::vector<uint8_t> vec2 {0x9f, 0x01};
CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec2),
"[json.exception.parse_error.110] parse error at 3: cannot read 1 bytes from vector");
// related test case: nonempty map (indefinite length)
std::vector<uint8_t> vec3 {0xbf, 0x61, 0x61, 0x01};
CHECK_THROWS_AS(json::from_cbor(vec3), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec3),
"[json.exception.parse_error.110] parse error at 5: cannot read 1 bytes from vector");
}
SECTION("issue #414 - compare with literal 0)")
@ -762,7 +794,9 @@ TEST_CASE("regression tests")
0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa
};
CHECK_THROWS_AS(json::from_cbor(vec1), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec1),
"[json.exception.parse_error.110] parse error at 49: cannot read 4 bytes from vector");
// related test case: double-precision
std::vector<uint8_t> vec2
@ -774,7 +808,9 @@ TEST_CASE("regression tests")
0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb
};
CHECK_THROWS_AS(json::from_cbor(vec2), std::out_of_range);
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error);
CHECK_THROWS_WITH(json::from_cbor(vec2),
"[json.exception.parse_error.110] parse error at 49: cannot read 8 bytes from vector");
}
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")