mirror of
https://github.com/nlohmann/json.git
synced 2026-10-06 22:47:13 +00:00
Fix NUL bytes in UBJSON/BJData high-precision numbers (#5760)
* Fix NUL-terminated UBJSON and BJData high-precision payloads Signed-off-by: fhgffy <102001626+fhgffy@users.noreply.github.com> * Use English comments for the high-precision NUL fix Signed-off-by: fhgffy <102001626+fhgffy@users.noreply.github.com> * Track NUL bytes while reading high-precision payloads Signed-off-by: fhgffy <102001626+fhgffy@users.noreply.github.com> * Drop dates from code comments. Signed-off-by: fhgffy <102001626+fhgffy@users.noreply.github.com> * Report a NUL in a high-precision number where it is read Return the parse error from the read loop so the byte offset points at the NUL, and drop the separate check after lexing. Signed-off-by: fhgffy <102001626+fhgffy@users.noreply.github.com> * Use fixed text for the high-precision NUL error 2026-10-06: Use the known zero byte directly instead of formatting and concatenating it. Preserve the SAX token, error message, and byte offset. Signed-off-by: fhgffy <102001626+fhgffy@users.noreply.github.com> --------- Signed-off-by: fhgffy <102001626+fhgffy@users.noreply.github.com>
This commit is contained in:
1 parent
a7d387a762
commit
69874e4544
4 files changed
+64
No files matched your search
@@ -3249,6 +3249,12 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// the lexer would stop at a NUL and accept the digits before it
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(current == '\0'))
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, "00", parse_error::create(115, chars_read,
|
||||||
|
exception_message("invalid number text; last byte: 0x00", "high-precision number"), nullptr));
|
||||||
|
}
|
||||||
number_vector.push_back(static_cast<char>(current));
|
number_vector.push_back(static_cast<char>(current));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16998,6 +16998,12 @@ class binary_reader
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// the lexer would stop at a NUL and accept the digits before it
|
||||||
|
if (JSON_HEDLEY_UNLIKELY(current == '\0'))
|
||||||
|
{
|
||||||
|
return sax->parse_error(chars_read, "00", parse_error::create(115, chars_read,
|
||||||
|
exception_message("invalid number text; last byte: 0x00", "high-precision number"), nullptr));
|
||||||
|
}
|
||||||
number_vector.push_back(static_cast<char>(current));
|
number_vector.push_back(static_cast<char>(current));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1286,6 +1286,32 @@ TEST_CASE("BJData")
|
|||||||
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1A", json::parse_error);
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1A", json::parse_error);
|
||||||
std::vector<uint8_t> const vec3 = {'H', 'i', 2, '1', '.'};
|
std::vector<uint8_t> const vec3 = {'H', 'i', 2, '1', '.'};
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1.", json::parse_error);
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1.", json::parse_error);
|
||||||
|
// Reject NULs where they are read, including trailing NULs and payloads cut off after one.
|
||||||
|
SECTION("NUL in high-precision number (issue #5753)")
|
||||||
|
{
|
||||||
|
for (const auto& vec : std::vector<std::vector<uint8_t>>
|
||||||
|
{
|
||||||
|
{'H', 'i', 3, '1', 0, 'x'},
|
||||||
|
{'H', 'i', 2, '1', 0},
|
||||||
|
{'H', 'i', 3, '1', 0}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(vec)
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text; last byte: 0x00", json::parse_error);
|
||||||
|
CHECK(json::from_bjdata(vec, true, false).is_discarded());
|
||||||
|
CHECK(json::from_bjdata(vec, false, false).is_discarded());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> const nested = {'[', 'H', 'i', 3, '1', 0, 'x', ']'};
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(nested), "[json.exception.parse_error.115] parse error at byte 6: syntax error while parsing BJData high-precision number: invalid number text; last byte: 0x00", json::parse_error);
|
||||||
|
CHECK(json::from_bjdata(nested, true, false).is_discarded());
|
||||||
|
|
||||||
|
std::vector<uint8_t> const valid = {'H', 'i', 1, '1'};
|
||||||
|
const auto j = json::from_bjdata(valid);
|
||||||
|
CHECK(j.is_number_unsigned());
|
||||||
|
CHECK(j == json(1));
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> const vec_overflow = {'H', 'i', 5, '1', 'e', '4', '0', '0'};
|
std::vector<uint8_t> const vec_overflow = {'H', 'i', 5, '1', 'e', '4', '0', '0'};
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec_overflow), "[json.exception.out_of_range.406] number overflow parsing '1e400'", json::out_of_range);
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec_overflow), "[json.exception.out_of_range.406] number overflow parsing '1e400'", json::out_of_range);
|
||||||
std::vector<uint8_t> const vec4 = {'H', 2, '1', '0'};
|
std::vector<uint8_t> const vec4 = {'H', 2, '1', '0'};
|
||||||
|
|||||||
@@ -802,6 +802,32 @@ TEST_CASE("UBJSON")
|
|||||||
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A", json::parse_error);
|
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A", json::parse_error);
|
||||||
std::vector<uint8_t> const vec3 = {'H', 'i', 2, '1', '.'};
|
std::vector<uint8_t> const vec3 = {'H', 'i', 2, '1', '.'};
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1.", json::parse_error);
|
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1.", json::parse_error);
|
||||||
|
// Reject NULs where they are read, including trailing NULs and payloads cut off after one.
|
||||||
|
SECTION("NUL in high-precision number (issue #5753)")
|
||||||
|
{
|
||||||
|
for (const auto& vec : std::vector<std::vector<uint8_t>>
|
||||||
|
{
|
||||||
|
{'H', 'i', 3, '1', 0, 'x'},
|
||||||
|
{'H', 'i', 2, '1', 0},
|
||||||
|
{'H', 'i', 3, '1', 0}
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(vec)
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text; last byte: 0x00", json::parse_error);
|
||||||
|
CHECK(json::from_ubjson(vec, true, false).is_discarded());
|
||||||
|
CHECK(json::from_ubjson(vec, false, false).is_discarded());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> const nested = {'[', 'H', 'i', 3, '1', 0, 'x', ']'};
|
||||||
|
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(nested), "[json.exception.parse_error.115] parse error at byte 6: syntax error while parsing UBJSON high-precision number: invalid number text; last byte: 0x00", json::parse_error);
|
||||||
|
CHECK(json::from_ubjson(nested, true, false).is_discarded());
|
||||||
|
|
||||||
|
std::vector<uint8_t> const valid = {'H', 'i', 1, '1'};
|
||||||
|
const auto j = json::from_ubjson(valid);
|
||||||
|
CHECK(j.is_number_unsigned());
|
||||||
|
CHECK(j == json(1));
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> const vec_overflow = {'H', 'i', 5, '1', 'e', '4', '0', '0'};
|
std::vector<uint8_t> const vec_overflow = {'H', 'i', 5, '1', 'e', '4', '0', '0'};
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec_overflow), "[json.exception.out_of_range.406] number overflow parsing '1e400'", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vec_overflow), "[json.exception.out_of_range.406] number overflow parsing '1e400'", json::out_of_range&);
|
||||||
std::vector<uint8_t> const vec4 = {'H', 2, '1', '0'};
|
std::vector<uint8_t> const vec4 = {'H', 2, '1', '0'};
|
||||||
|
|||||||
Reference in new issue
Block a user