🚑 fix for #408

This commit is contained in:
Niels Lohmann 2016-12-29 17:00:02 +01:00
parent 383a29a924
commit f0edab2363
3 changed files with 52 additions and 62 deletions

View file

@ -6879,27 +6879,6 @@ class basic_json
} }
} }
/*!
@brief checks if a given length does not exceed the size of a given vector
To secure the access to the byte vector during CBOR/MessagePack
deserialization, bytes are copied from the vector into buffers. This
function checks if the number of bytes to copy (@a len) does not exceed the
size of the given vector @a vec.
@param[in] vec byte vector
@param[in] len length
@throws out_of_range if `len > v.size()`
*/
static void check_length(const std::vector<uint8_t>& vec, const size_t& len)
{
if (len > vec.size())
{
throw std::out_of_range("len out of range");
}
}
/*! /*!
@brief create a JSON value from a given MessagePack vector @brief create a JSON value from a given MessagePack vector
@ -6916,6 +6895,9 @@ class basic_json
*/ */
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx) static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
{ {
// make sure reading 1 byte is safe
check_length(v.size(), 1, idx);
// store and increment index // store and increment index
const size_t current_idx = idx++; const size_t current_idx = idx++;
@ -7153,6 +7135,9 @@ class basic_json
*/ */
static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx) static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
{ {
// make sure reading 1 byte is safe
check_length(v.size(), 1, idx);
// store and increment index // store and increment index
const size_t current_idx = idx++; const size_t current_idx = idx++;
@ -7674,11 +7659,6 @@ class basic_json
*/ */
static basic_json from_msgpack(const std::vector<uint8_t>& v) static basic_json from_msgpack(const std::vector<uint8_t>& v)
{ {
if (v.empty())
{
throw std::invalid_argument("empty vector");
}
size_t i = 0; size_t i = 0;
return from_msgpack_internal(v, i); return from_msgpack_internal(v, i);
} }
@ -7736,11 +7716,6 @@ class basic_json
*/ */
static basic_json from_cbor(const std::vector<uint8_t>& v) static basic_json from_cbor(const std::vector<uint8_t>& v)
{ {
if (v.empty())
{
throw std::invalid_argument("empty vector");
}
size_t i = 0; size_t i = 0;
return from_cbor_internal(v, i); return from_cbor_internal(v, i);
} }

View file

@ -6879,27 +6879,6 @@ class basic_json
} }
} }
/*!
@brief checks if a given length does not exceed the size of a given vector
To secure the access to the byte vector during CBOR/MessagePack
deserialization, bytes are copied from the vector into buffers. This
function checks if the number of bytes to copy (@a len) does not exceed the
size of the given vector @a vec.
@param[in] vec byte vector
@param[in] len length
@throws out_of_range if `len > v.size()`
*/
static void check_length(const std::vector<uint8_t>& vec, const size_t& len)
{
if (len > vec.size())
{
throw std::out_of_range("len out of range");
}
}
/*! /*!
@brief create a JSON value from a given MessagePack vector @brief create a JSON value from a given MessagePack vector
@ -6916,6 +6895,9 @@ class basic_json
*/ */
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx) static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
{ {
// make sure reading 1 byte is safe
check_length(v.size(), 1, idx);
// store and increment index // store and increment index
const size_t current_idx = idx++; const size_t current_idx = idx++;
@ -7153,6 +7135,9 @@ class basic_json
*/ */
static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx) static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
{ {
// make sure reading 1 byte is safe
check_length(v.size(), 1, idx);
// store and increment index // store and increment index
const size_t current_idx = idx++; const size_t current_idx = idx++;
@ -7674,11 +7659,6 @@ class basic_json
*/ */
static basic_json from_msgpack(const std::vector<uint8_t>& v) static basic_json from_msgpack(const std::vector<uint8_t>& v)
{ {
if (v.empty())
{
throw std::invalid_argument("empty vector");
}
size_t i = 0; size_t i = 0;
return from_msgpack_internal(v, i); return from_msgpack_internal(v, i);
} }
@ -7736,11 +7716,6 @@ class basic_json
*/ */
static basic_json from_cbor(const std::vector<uint8_t>& v) static basic_json from_cbor(const std::vector<uint8_t>& v)
{ {
if (v.empty())
{
throw std::invalid_argument("empty vector");
}
size_t i = 0; size_t i = 0;
return from_cbor_internal(v, i); return from_cbor_internal(v, i);
} }

View file

@ -570,4 +570,44 @@ TEST_CASE("regression tests")
std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a}; 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), std::out_of_range);
} }
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);
// more test cases for MessagePack
for (uint8_t b :
{
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // fixmap
0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // fixarray
0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, // fixstr
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf
})
{
std::vector<uint8_t> vec(1, b);
CHECK_THROWS_AS(json::from_msgpack(vec), std::out_of_range);
}
// more test cases for CBOR
for (uint8_t b :
{
0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // UTF-8 string
0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // array
0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 // map
})
{
std::vector<uint8_t> vec(1, b);
CHECK_THROWS_AS(json::from_cbor(vec), std::out_of_range);
}
// 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);
}
} }