mirror of
https://github.com/nlohmann/json.git
synced 2026-07-24 04:33:02 +04:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a3ebb9456 | |||
| 3296a3ad8c |
@@ -15,6 +15,14 @@ guidance.
|
||||
|
||||
For vulnerabilities in third-party dependencies or modules, please report them directly to the respective maintainers.
|
||||
|
||||
## Unofficial packages
|
||||
|
||||
This project does not publish an official npm package. The npm package
|
||||
[`nlohmann-json`](https://www.npmjs.com/package/nlohmann-json) (or similarly named packages) is not maintained or
|
||||
endorsed by this project. See the
|
||||
[package managers documentation](https://json.nlohmann.me/integration/package_managers/#npm) for supported
|
||||
integration options.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- Explore security-related topics and contribute to tools and projects through
|
||||
|
||||
@@ -930,6 +930,12 @@ If you are using [CocoaPods](https://cocoapods.org), you can use the library by
|
||||
to your podfile (see [an example](https://bitbucket.org/benman/nlohmann_json-cocoapod/src/master/)). Please file issues
|
||||
[here](https://bitbucket.org/benman/nlohmann_json-cocoapod/issues?status=new&status=open).
|
||||
|
||||
## npm
|
||||
|
||||
This project does not publish an official [npm](https://www.npmjs.com) package. The npm package
|
||||
[`nlohmann-json`](https://www.npmjs.com/package/nlohmann-json) (or similarly named packages) is not maintained or
|
||||
endorsed by this project. Use one of the package managers listed above, or integrate the single header directly.
|
||||
|
||||
## ESP-IDF and PlatformIO
|
||||
|
||||
There is no official package published to the [ESP-IDF Component Registry](https://components.espressif.com) or the
|
||||
|
||||
@@ -163,12 +163,39 @@ class binary_reader
|
||||
// BSON //
|
||||
//////////
|
||||
|
||||
/*!
|
||||
@brief Validate a BSON document's declared size against the bytes read.
|
||||
|
||||
A BSON document starts with an int32 that counts its own total length in
|
||||
bytes, including that prefix and the trailing 0x00. The reader is driven
|
||||
by the terminator rather than the declared length, so without this check a
|
||||
nested document could declare a length that disagrees with where its
|
||||
terminator actually falls and quietly hand the bytes in between to the
|
||||
enclosing document. A well-formed document is at least 5 bytes (the prefix
|
||||
plus the terminator); the equality also rejects those impossible sizes,
|
||||
since at least 5 bytes are always consumed.
|
||||
|
||||
@param[in] document_start value of chars_read before the size prefix
|
||||
@param[in] document_size the declared document size
|
||||
@return whether the declared size matches the number of bytes read
|
||||
*/
|
||||
bool check_bson_document_size(const std::size_t document_start, const std::int32_t document_size)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
||||
{
|
||||
return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
|
||||
exception_message(input_format_t::bson, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Reads in a BSON-object and passes it to the SAX-parser.
|
||||
@return whether a valid BSON-value was passed to the SAX parser
|
||||
*/
|
||||
bool parse_bson_internal()
|
||||
{
|
||||
const std::size_t document_start = chars_read;
|
||||
std::int32_t document_size{};
|
||||
get_number<std::int32_t, true>(input_format_t::bson, document_size);
|
||||
|
||||
@@ -182,6 +209,11 @@ class binary_reader
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_bson_document_size(document_start, document_size)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return sax->end_object();
|
||||
}
|
||||
|
||||
@@ -397,6 +429,7 @@ class binary_reader
|
||||
*/
|
||||
bool parse_bson_array()
|
||||
{
|
||||
const std::size_t document_start = chars_read;
|
||||
std::int32_t document_size{};
|
||||
get_number<std::int32_t, true>(input_format_t::bson, document_size);
|
||||
|
||||
@@ -410,6 +443,11 @@ class binary_reader
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_bson_document_size(document_start, document_size)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return sax->end_array();
|
||||
}
|
||||
|
||||
|
||||
@@ -10712,12 +10712,39 @@ class binary_reader
|
||||
// BSON //
|
||||
//////////
|
||||
|
||||
/*!
|
||||
@brief Validate a BSON document's declared size against the bytes read.
|
||||
|
||||
A BSON document starts with an int32 that counts its own total length in
|
||||
bytes, including that prefix and the trailing 0x00. The reader is driven
|
||||
by the terminator rather than the declared length, so without this check a
|
||||
nested document could declare a length that disagrees with where its
|
||||
terminator actually falls and quietly hand the bytes in between to the
|
||||
enclosing document. A well-formed document is at least 5 bytes (the prefix
|
||||
plus the terminator); the equality also rejects those impossible sizes,
|
||||
since at least 5 bytes are always consumed.
|
||||
|
||||
@param[in] document_start value of chars_read before the size prefix
|
||||
@param[in] document_size the declared document size
|
||||
@return whether the declared size matches the number of bytes read
|
||||
*/
|
||||
bool check_bson_document_size(const std::size_t document_start, const std::int32_t document_size)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(document_size < 0 || static_cast<std::size_t>(document_size) != chars_read - document_start))
|
||||
{
|
||||
return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
|
||||
exception_message(input_format_t::bson, concat("document size ", std::to_string(document_size), " does not match the number of bytes read (", std::to_string(chars_read - document_start), ")"), "document"), nullptr));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Reads in a BSON-object and passes it to the SAX-parser.
|
||||
@return whether a valid BSON-value was passed to the SAX parser
|
||||
*/
|
||||
bool parse_bson_internal()
|
||||
{
|
||||
const std::size_t document_start = chars_read;
|
||||
std::int32_t document_size{};
|
||||
get_number<std::int32_t, true>(input_format_t::bson, document_size);
|
||||
|
||||
@@ -10731,6 +10758,11 @@ class binary_reader
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_bson_document_size(document_start, document_size)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return sax->end_object();
|
||||
}
|
||||
|
||||
@@ -10946,6 +10978,7 @@ class binary_reader
|
||||
*/
|
||||
bool parse_bson_array()
|
||||
{
|
||||
const std::size_t document_start = chars_read;
|
||||
std::int32_t document_size{};
|
||||
get_number<std::int32_t, true>(input_format_t::bson, document_size);
|
||||
|
||||
@@ -10959,6 +10992,11 @@ class binary_reader
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!check_bson_document_size(document_start, document_size)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return sax->end_array();
|
||||
}
|
||||
|
||||
|
||||
@@ -854,6 +854,62 @@ TEST_CASE("Unsupported BSON input")
|
||||
CHECK(!json::sax_parse(bson, &scp, json::input_format_t::bson));
|
||||
}
|
||||
|
||||
TEST_CASE("BSON document size mismatch")
|
||||
{
|
||||
json _;
|
||||
|
||||
SECTION("top-level document declaring more bytes than it contains")
|
||||
{
|
||||
// empty object, but the length prefix claims 6 bytes instead of 5
|
||||
std::vector<std::uint8_t> const input = {0x06, 0x00, 0x00, 0x00, 0x00};
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bson(input), "[json.exception.parse_error.112] parse error at byte 5: syntax error while parsing BSON document: document size 6 does not match the number of bytes read (5)", json::parse_error&);
|
||||
CHECK(json::from_bson(input, true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("top-level document with a negative size")
|
||||
{
|
||||
std::vector<std::uint8_t> const input = {0xFF, 0xFF, 0xFF, 0xFF, 0x00};
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bson(input), "[json.exception.parse_error.112] parse error at byte 5: syntax error while parsing BSON document: document size -1 does not match the number of bytes read (5)", json::parse_error&);
|
||||
CHECK(json::from_bson(input, true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("embedded document whose size disagrees with its terminator")
|
||||
{
|
||||
// the embedded document "d" declares 0x7FFFFFFF bytes but its 0x00
|
||||
// terminator falls right after {"a":null}; the length prefix would
|
||||
// otherwise let the following "h" element be read as a member of the
|
||||
// enclosing document instead of "d"
|
||||
std::vector<std::uint8_t> const input =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, // outer size
|
||||
0x03, 'd', 0x00, // entry: embedded document "d"
|
||||
0xFF, 0xFF, 0xFF, 0x7F, // embedded size 0x7FFFFFFF
|
||||
0x0A, 'a', 0x00, // entry: null "a"
|
||||
0x00, // embedded end marker
|
||||
0x08, 'h', 0x00, 0x01, // entry: bool "h" = true
|
||||
0x00 // outer end marker
|
||||
};
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bson(input), "[json.exception.parse_error.112] parse error at byte 15: syntax error while parsing BSON document: document size 2147483647 does not match the number of bytes read (8)", json::parse_error&);
|
||||
CHECK(json::from_bson(input, true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("embedded array whose size disagrees with its terminator")
|
||||
{
|
||||
// array [42] is 12 bytes, but the length prefix claims 13
|
||||
std::vector<std::uint8_t> const input =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, // outer size
|
||||
0x04, 'a', 0x00, // entry: array "a"
|
||||
0x0D, 0x00, 0x00, 0x00, // array size 13 (real is 12)
|
||||
0x10, '0', 0x00, 0x2A, 0x00, 0x00, 0x00, // entry: int32 "0" = 42
|
||||
0x00, // array end marker
|
||||
0x00 // outer end marker
|
||||
};
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bson(input), "[json.exception.parse_error.112] parse error at byte 19: syntax error while parsing BSON document: document size 13 does not match the number of bytes read (12)", json::parse_error&);
|
||||
CHECK(json::from_bson(input, true, false).is_discarded());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("BSON numerical data")
|
||||
{
|
||||
SECTION("number")
|
||||
|
||||
Reference in New Issue
Block a user