mirror of
https://github.com/nlohmann/json.git
synced 2026-09-30 11:40:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af25bf67f3 |
@@ -139,8 +139,8 @@ basic_json(basic_json&& other) noexcept;
|
||||
|
||||
- In case of a `#!json null` type, [invalid_iterator.206](../../home/exceptions.md#jsonexceptioninvalid_iterator206)
|
||||
is thrown.
|
||||
- In case of other primitive types (number, boolean, string, or binary), `first` must be `begin()` and `last`
|
||||
must be `end()`. In this case, the value is copied. Otherwise,
|
||||
- In case of other primitive types (number, boolean, or string), `first` must be `begin()` and `last` must be
|
||||
`end()`. In this case, the value is copied. Otherwise,
|
||||
[`invalid_iterator.204`](../../home/exceptions.md#jsonexceptioninvalid_iterator204) is thrown.
|
||||
- In case of structured types (array, object), the constructor behaves as similar versions for `std::vector` or
|
||||
`std::map`; that is, a JSON array or object is constructed from the values in the range.
|
||||
@@ -242,8 +242,8 @@ basic_json(basic_json&& other) noexcept;
|
||||
and `last` are not compatible (i.e., do not belong to the same JSON value). In this case, the range
|
||||
`[first, last)` is undefined.
|
||||
- Throws [`invalid_iterator.204`](../../home/exceptions.md#jsonexceptioninvalid_iterator204) if iterators `first`
|
||||
and `last` belong to a primitive type (number, boolean, string, or binary), but `first` does not point to the
|
||||
first element anymore. In this case, the range `[first, last)` is undefined. See the example code below.
|
||||
and `last` belong to a primitive type (number, boolean, or string), but `first` does not point to the first
|
||||
element anymore. In this case, the range `[first, last)` is undefined. See the example code below.
|
||||
- Throws [`invalid_iterator.206`](../../home/exceptions.md#jsonexceptioninvalid_iterator206) if iterators `first`
|
||||
and `last` belong to a `#!json null` value. In this case, the range `[first, last)` is undefined.
|
||||
8. (none)
|
||||
@@ -423,8 +423,6 @@ basic_json(basic_json&& other) noexcept;
|
||||
4. Since version 3.2.0.
|
||||
5. Since version 1.0.0.
|
||||
6. Since version 1.0.0.
|
||||
7. Since version 1.0.0. Fixed in version 3.13.0 to also check the iterator range for binary values; before, a range
|
||||
that did not cover the whole value (such as `(end(), end())`) was accepted and the whole binary value was copied,
|
||||
unlike the other primitive types.
|
||||
7. Since version 1.0.0.
|
||||
8. Since version 1.0.0.
|
||||
9. Since version 1.0.0.
|
||||
|
||||
@@ -3821,6 +3821,11 @@ class binary_reader
|
||||
if (0xC2 <= byte && byte <= 0xF7)
|
||||
{
|
||||
const auto second = get_bon8();
|
||||
if (second == char_traits<char_type>::eof())
|
||||
{
|
||||
// the input ends inside a character or an integer
|
||||
return unexpect_eof(input_format_t::bon8, "key");
|
||||
}
|
||||
unget_bon8(second);
|
||||
if (is_bon8_continuation(second))
|
||||
{
|
||||
@@ -3919,6 +3924,12 @@ class binary_reader
|
||||
// a lead byte ends the string if no continuation byte follows: it
|
||||
// is then the first byte of an integer
|
||||
const auto second = get_bon8();
|
||||
if (second == char_traits<char_type>::eof())
|
||||
{
|
||||
// the input ends inside a character or an integer: either
|
||||
// way, the message is incomplete
|
||||
return unexpect_eof(input_format_t::bon8, "string");
|
||||
}
|
||||
if (!is_bon8_continuation(second))
|
||||
{
|
||||
unget_bon8(second);
|
||||
|
||||
@@ -1829,7 +1829,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
case value_t::number_integer:
|
||||
case value_t::number_unsigned:
|
||||
case value_t::string:
|
||||
case value_t::binary:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
|
||||
|| !last.m_it.primitive_iterator.is_end()))
|
||||
@@ -1842,6 +1841,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
case value_t::null:
|
||||
case value_t::object:
|
||||
case value_t::array:
|
||||
case value_t::binary:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -16588,6 +16588,11 @@ class binary_reader
|
||||
if (0xC2 <= byte && byte <= 0xF7)
|
||||
{
|
||||
const auto second = get_bon8();
|
||||
if (second == char_traits<char_type>::eof())
|
||||
{
|
||||
// the input ends inside a character or an integer
|
||||
return unexpect_eof(input_format_t::bon8, "key");
|
||||
}
|
||||
unget_bon8(second);
|
||||
if (is_bon8_continuation(second))
|
||||
{
|
||||
@@ -16686,6 +16691,12 @@ class binary_reader
|
||||
// a lead byte ends the string if no continuation byte follows: it
|
||||
// is then the first byte of an integer
|
||||
const auto second = get_bon8();
|
||||
if (second == char_traits<char_type>::eof())
|
||||
{
|
||||
// the input ends inside a character or an integer: either
|
||||
// way, the message is incomplete
|
||||
return unexpect_eof(input_format_t::bon8, "string");
|
||||
}
|
||||
if (!is_bon8_continuation(second))
|
||||
{
|
||||
unget_bon8(second);
|
||||
@@ -27910,7 +27921,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
case value_t::number_integer:
|
||||
case value_t::number_unsigned:
|
||||
case value_t::string:
|
||||
case value_t::binary:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
|
||||
|| !last.m_it.primitive_iterator.is_end()))
|
||||
@@ -27923,6 +27933,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
case value_t::null:
|
||||
case value_t::object:
|
||||
case value_t::array:
|
||||
case value_t::binary:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -531,6 +531,47 @@ TEST_CASE("BON8")
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x87, 'a'}), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BON8 string: unexpected end of input", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("input that ends after a UTF-8 lead byte")
|
||||
{
|
||||
// the lead byte begins either a character or an integer; both are
|
||||
// incomplete, so the lead byte must not end the string before it
|
||||
for (const bool strict :
|
||||
{
|
||||
true, false
|
||||
})
|
||||
{
|
||||
CAPTURE(strict)
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{'a', 0xC3}, strict), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BON8 string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x81, 'a', 0xC3}, strict), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BON8 string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x81, 'a', 0xE2}, strict), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BON8 string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x81, 'a', 0xF0}, strict), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BON8 string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x81, 0xC3, 0xA9, 0xC3}, strict), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BON8 string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x87, 'a', 0xC3}, strict), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BON8 string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x87, 0xC3}, strict), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BON8 key: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_bon8(bytes{0x88, 'a', 0x91, 0xE2}, strict), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BON8 key: unexpected end of input", json::parse_error&);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("a message that is cut off is not read as a shorter value")
|
||||
{
|
||||
const json values = {"\xC3\xA9", "a\xE2\x82\xAC", "\xF0\x9F\x98\x80\xC3\xA9", {"a\xC3\xA9"}, {{"\xC3\xA9", "\xE2\x82\xAC"}}, {{"a", {"b\xC3\xA9", 1}}}};
|
||||
for (const auto& j : values)
|
||||
{
|
||||
const bytes message = json::to_bon8(j);
|
||||
for (std::size_t length = 0; length < message.size(); ++length)
|
||||
{
|
||||
CAPTURE(j)
|
||||
CAPTURE(length)
|
||||
bytes prefix = message;
|
||||
prefix.resize(length);
|
||||
CHECK(json::from_bon8(prefix, false, false).is_discarded());
|
||||
// a stream is read byte by byte rather than in bulk
|
||||
std::istringstream stream(str(prefix));
|
||||
CHECK(json::from_bon8(stream, false, false).is_discarded());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("invalid UTF-8")
|
||||
{
|
||||
// overlong
|
||||
|
||||
@@ -1648,20 +1648,6 @@ TEST_CASE("constructors")
|
||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("binary")
|
||||
{
|
||||
{
|
||||
json j = json::binary({1, 2, 3});
|
||||
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||
}
|
||||
{
|
||||
json const j = json::binary({1, 2, 3});
|
||||
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user