🚧 a lot of minor changes

- Removed unused headers.
- Added override where needed.
- Added description for parse_error.113 exception.
- Fixed some conversion warnings.
- Integrated cbor_expect_string function for CBOR maps.
- Added documentation on the supported CBOR/MessagePack features.
- Added test to check all initial bytes for CBOR input.
This commit is contained in:
Niels Lohmann 2017-03-16 18:39:33 +01:00
parent 483a58f625
commit c5711f3072
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
10 changed files with 385 additions and 90 deletions

View file

@ -130,14 +130,14 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x3b);
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
(static_cast<uint64_t>(result[2]) << 060) +
(static_cast<uint64_t>(result[3]) << 050) +
(static_cast<uint64_t>(result[4]) << 040) +
(static_cast<uint64_t>(result[5]) << 030) +
(static_cast<uint64_t>(result[6]) << 020) +
(static_cast<uint64_t>(result[7]) << 010) +
static_cast<uint64_t>(result[8]));
static_cast<uint64_t>(result[8]);
CHECK(restored == positive);
CHECK(-1 - static_cast<int64_t>(restored) == i);
@ -182,10 +182,10 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x3a);
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
(static_cast<uint32_t>(result[2]) << 020) +
(static_cast<uint32_t>(result[3]) << 010) +
static_cast<uint32_t>(result[4]));
static_cast<uint32_t>(result[4]);
CHECK(restored == positive);
CHECK(-1ll - restored == i);
@ -220,7 +220,7 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x39);
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
CHECK(restored == positive);
CHECK(-1 - restored == i);
@ -289,7 +289,7 @@ TEST_CASE("CBOR")
// create expected byte vector
std::vector<uint8_t> expected;
expected.push_back(0x20 - 1 - static_cast<uint8_t>(i));
expected.push_back(static_cast<uint8_t>(0x20 - 1 - static_cast<uint8_t>(i)));
// compare result + size
const auto result = json::to_cbor(j);
@ -392,7 +392,7 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x19);
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
CHECK(restored == i);
// roundtrip
@ -431,10 +431,10 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x1a);
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
(static_cast<uint32_t>(result[2]) << 020) +
(static_cast<uint32_t>(result[3]) << 010) +
static_cast<uint32_t>(result[4]));
static_cast<uint32_t>(result[4]);
CHECK(restored == i);
// roundtrip
@ -477,14 +477,14 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x1b);
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
(static_cast<uint64_t>(result[2]) << 060) +
(static_cast<uint64_t>(result[3]) << 050) +
(static_cast<uint64_t>(result[4]) << 040) +
(static_cast<uint64_t>(result[5]) << 030) +
(static_cast<uint64_t>(result[6]) << 020) +
(static_cast<uint64_t>(result[7]) << 010) +
static_cast<uint64_t>(result[8]));
static_cast<uint64_t>(result[8]);
CHECK(restored == i);
// roundtrip
@ -616,7 +616,7 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x19);
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
CHECK(restored == i);
// roundtrip
@ -654,10 +654,10 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x1a);
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
(static_cast<uint32_t>(result[2]) << 020) +
(static_cast<uint32_t>(result[3]) << 010) +
static_cast<uint32_t>(result[4]));
static_cast<uint32_t>(result[4]);
CHECK(restored == i);
// roundtrip
@ -699,14 +699,14 @@ TEST_CASE("CBOR")
// check individual bytes
CHECK(result[0] == 0x1b);
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
(static_cast<uint64_t>(result[2]) << 060) +
(static_cast<uint64_t>(result[3]) << 050) +
(static_cast<uint64_t>(result[4]) << 040) +
(static_cast<uint64_t>(result[5]) << 030) +
(static_cast<uint64_t>(result[6]) << 020) +
(static_cast<uint64_t>(result[7]) << 010) +
static_cast<uint64_t>(result[8]));
static_cast<uint64_t>(result[8]);
CHECK(restored == i);
// roundtrip
@ -1538,6 +1538,83 @@ TEST_CASE("CBOR roundtrips", "[hide]")
}
}
TEST_CASE("all first bytes", "[!throws]")
{
// these bytes will fail immediately with exception parse_error.112
std::set<uint8_t> unsupported =
{
//// types not supported by this library
// byte strings
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
// byte strings
0x58, 0x59, 0x5a, 0x5b, 0x5f,
// date/time
0xc0, 0xc1,
// bignum
0xc2, 0xc3,
// decimal fracion
0xc4,
// bigfloat
0xc5,
// tagged item
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd8,
0xd9, 0xda, 0xdb,
// expected conversion
0xd5, 0xd6, 0xd7,
// simple value
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xef, 0xf0,
0xf1, 0xf2, 0xf3,
0xf8,
// undefined
0xf7,
//// bytes not specified by CBOR
0x1c, 0x1d, 0x1e, 0x1f,
0x3c, 0x3d, 0x3e, 0x3f,
0x5c, 0x5d, 0x5e,
0x7c, 0x7d, 0x7e,
0x9c, 0x9d, 0x9e,
0xbc, 0xbd, 0xbe,
0xdc, 0xdd, 0xde, 0xdf,
0xee,
0xfc, 0xfe, 0xfd,
/// break cannot be the first byte
0xff
};
for (auto i = 0; i < 256; ++i)
{
const auto byte = static_cast<uint8_t>(i);
try
{
json::from_cbor({byte});
}
catch (const json::parse_error& e)
{
// check that parse_error.112 is only thrown if the
// first byte is in the unsupported set
CAPTURE(e.what());
if (std::find(unsupported.begin(), unsupported.end(), byte) != unsupported.end())
{
CHECK(e.id == 112);
}
else
{
CHECK(e.id != 112);
}
}
}
}
TEST_CASE("examples from RFC 7049 Appendix A")
{
SECTION("numbers")

View file

@ -139,7 +139,7 @@ TEST_CASE("lexer class")
for (int c = 1; c < 128; ++c)
{
// create string from the ASCII code
const auto s = std::string(1, c);
const auto s = std::string(1, static_cast<char>(c));
// store scan() result
const auto res = json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(s.c_str()),
1).scan();

View file

@ -494,7 +494,7 @@ TEST_CASE("parser class")
// invalid escapes
for (int c = 1; c < 128; ++c)
{
auto s = std::string("\"\\") + std::string(1, c) + "\"";
auto s = std::string("\"\\") + std::string(1, static_cast<char>(c)) + "\"";
switch (c)
{
@ -574,10 +574,10 @@ TEST_CASE("parser class")
std::string s = "\"\\u";
// create a string with the iterated character at each position
auto s1 = s + "000" + std::string(1, c) + "\"";
auto s2 = s + "00" + std::string(1, c) + "0\"";
auto s3 = s + "0" + std::string(1, c) + "00\"";
auto s4 = s + std::string(1, c) + "000\"";
auto s1 = s + "000" + std::string(1, static_cast<char>(c)) + "\"";
auto s2 = s + "00" + std::string(1, static_cast<char>(c)) + "0\"";
auto s3 = s + "0" + std::string(1, static_cast<char>(c)) + "00\"";
auto s4 = s + std::string(1, static_cast<char>(c)) + "000\"";
if (valid(c))
{

View file

@ -72,8 +72,8 @@ TEST_CASE("concepts")
// X::size_type must return an unsigned integer
CHECK((std::is_unsigned<json::size_type>::value));
// X::size_type can represent any non-negative value of X::difference_type
CHECK(static_cast<size_t>(std::numeric_limits<json::difference_type>::max()) <=
static_cast<size_t>(std::numeric_limits<json::size_type>::max()));
CHECK(static_cast<json::size_type>(std::numeric_limits<json::difference_type>::max()) <=
std::numeric_limits<json::size_type>::max());
// the expression "X u" has the post-condition "u.empty()"
{

View file

@ -48,7 +48,7 @@ TEST_CASE("element access 1")
CHECK(j.at(3) == json(nullptr));
CHECK(j.at(4) == json("string"));
CHECK(j.at(5) == json(42.23));
CHECK(j.at(6) == json(json::object()));
CHECK(j.at(6) == json::object());
CHECK(j.at(7) == json({1, 2, 3}));
CHECK(j_const.at(0) == json(1));
@ -57,7 +57,7 @@ TEST_CASE("element access 1")
CHECK(j_const.at(3) == json(nullptr));
CHECK(j_const.at(4) == json("string"));
CHECK(j_const.at(5) == json(42.23));
CHECK(j_const.at(6) == json(json::object()));
CHECK(j_const.at(6) == json::object());
CHECK(j_const.at(7) == json({1, 2, 3}));
}
@ -171,7 +171,7 @@ TEST_CASE("element access 1")
CHECK(j[3] == json(nullptr));
CHECK(j[4] == json("string"));
CHECK(j[5] == json(42.23));
CHECK(j[6] == json(json::object()));
CHECK(j[6] == json::object());
CHECK(j[7] == json({1, 2, 3}));
CHECK(j_const[0] == json(1));
@ -180,7 +180,7 @@ TEST_CASE("element access 1")
CHECK(j_const[3] == json(nullptr));
CHECK(j_const[4] == json("string"));
CHECK(j_const[5] == json(42.23));
CHECK(j_const[6] == json(json::object()));
CHECK(j_const[6] == json::object());
CHECK(j_const[7] == json({1, 2, 3}));
}

View file

@ -48,7 +48,7 @@ TEST_CASE("element access 2")
CHECK(j.at("null") == json(nullptr));
CHECK(j.at("string") == json("hello world"));
CHECK(j.at("floating") == json(42.23));
CHECK(j.at("object") == json(json::object()));
CHECK(j.at("object") == json::object());
CHECK(j.at("array") == json({1, 2, 3}));
CHECK(j_const.at("integer") == json(1));
@ -57,7 +57,7 @@ TEST_CASE("element access 2")
CHECK(j_const.at("null") == json(nullptr));
CHECK(j_const.at("string") == json("hello world"));
CHECK(j_const.at("floating") == json(42.23));
CHECK(j_const.at("object") == json(json::object()));
CHECK(j_const.at("object") == json::object());
CHECK(j_const.at("array") == json({1, 2, 3}));
}
@ -161,7 +161,7 @@ TEST_CASE("element access 2")
CHECK(j.value("string", std::string("bar")) == "hello world");
CHECK(j.value("floating", 12.34) == Approx(42.23));
CHECK(j.value("floating", 12) == 42);
CHECK(j.value("object", json({{"foo", "bar"}})) == json(json::object()));
CHECK(j.value("object", json({{"foo", "bar"}})) == json::object());
CHECK(j.value("array", json({10, 100})) == json({1, 2, 3}));
CHECK(j_const.value("integer", 2) == 1);
@ -173,7 +173,7 @@ TEST_CASE("element access 2")
CHECK(j_const.value("string", std::string("bar")) == "hello world");
CHECK(j_const.value("floating", 12.34) == Approx(42.23));
CHECK(j_const.value("floating", 12) == 42);
CHECK(j_const.value("object", json({{"foo", "bar"}})) == json(json::object()));
CHECK(j_const.value("object", json({{"foo", "bar"}})) == json::object());
CHECK(j_const.value("array", json({10, 100})) == json({1, 2, 3}));
}
@ -298,7 +298,7 @@ TEST_CASE("element access 2")
CHECK(j.value("/string"_json_pointer, std::string("bar")) == "hello world");
CHECK(j.value("/floating"_json_pointer, 12.34) == Approx(42.23));
CHECK(j.value("/floating"_json_pointer, 12) == 42);
CHECK(j.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
CHECK(j.value("/object"_json_pointer, json({{"foo", "bar"}})) == json::object());
CHECK(j.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
CHECK(j_const.value("/integer"_json_pointer, 2) == 1);
@ -310,7 +310,7 @@ TEST_CASE("element access 2")
CHECK(j_const.value("/string"_json_pointer, std::string("bar")) == "hello world");
CHECK(j_const.value("/floating"_json_pointer, 12.34) == Approx(42.23));
CHECK(j_const.value("/floating"_json_pointer, 12) == 42);
CHECK(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
CHECK(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})) == json::object());
CHECK(j_const.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
}
@ -435,7 +435,7 @@ TEST_CASE("element access 2")
CHECK(j["floating"] == json(42.23));
CHECK(j[json::object_t::key_type("floating")] == j["floating"]);
CHECK(j["object"] == json(json::object()));
CHECK(j["object"] == json::object());
CHECK(j[json::object_t::key_type("object")] == j["object"]);
CHECK(j["array"] == json({1, 2, 3}));
@ -456,7 +456,7 @@ TEST_CASE("element access 2")
CHECK(j_const["floating"] == json(42.23));
CHECK(j_const[json::object_t::key_type("floating")] == j["floating"]);
CHECK(j_const["object"] == json(json::object()));
CHECK(j_const["object"] == json::object());
CHECK(j_const[json::object_t::key_type("object")] == j["object"]);
CHECK(j_const["array"] == json({1, 2, 3}));

View file

@ -203,7 +203,7 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xcd);
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
CHECK(restored == i);
// roundtrip
@ -242,10 +242,10 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xce);
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
(static_cast<uint32_t>(result[2]) << 020) +
(static_cast<uint32_t>(result[3]) << 010) +
static_cast<uint32_t>(result[4]));
static_cast<uint32_t>(result[4]);
CHECK(restored == i);
// roundtrip
@ -288,14 +288,14 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xcf);
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
(static_cast<uint64_t>(result[2]) << 060) +
(static_cast<uint64_t>(result[3]) << 050) +
(static_cast<uint64_t>(result[4]) << 040) +
(static_cast<uint64_t>(result[5]) << 030) +
(static_cast<uint64_t>(result[6]) << 020) +
(static_cast<uint64_t>(result[7]) << 010) +
static_cast<uint64_t>(result[8]));
static_cast<uint64_t>(result[8]);
CHECK(restored == i);
// roundtrip
@ -415,10 +415,10 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xd2);
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
(static_cast<uint32_t>(result[2]) << 020) +
(static_cast<uint32_t>(result[3]) << 010) +
static_cast<uint32_t>(result[4]));
static_cast<uint32_t>(result[4]);
CHECK(restored == i);
// roundtrip
@ -460,14 +460,14 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xd3);
int64_t restored = static_cast<int64_t>((static_cast<int64_t>(result[1]) << 070) +
(static_cast<int64_t>(result[2]) << 060) +
(static_cast<int64_t>(result[3]) << 050) +
(static_cast<int64_t>(result[4]) << 040) +
(static_cast<int64_t>(result[5]) << 030) +
(static_cast<int64_t>(result[6]) << 020) +
(static_cast<int64_t>(result[7]) << 010) +
static_cast<int64_t>(result[8]));
int64_t restored = (static_cast<int64_t>(result[1]) << 070) +
(static_cast<int64_t>(result[2]) << 060) +
(static_cast<int64_t>(result[3]) << 050) +
(static_cast<int64_t>(result[4]) << 040) +
(static_cast<int64_t>(result[5]) << 030) +
(static_cast<int64_t>(result[6]) << 020) +
(static_cast<int64_t>(result[7]) << 010) +
static_cast<int64_t>(result[8]);
CHECK(restored == i);
// roundtrip
@ -564,7 +564,7 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xcd);
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
CHECK(restored == i);
// roundtrip
@ -602,10 +602,10 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xce);
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
(static_cast<uint32_t>(result[2]) << 020) +
(static_cast<uint32_t>(result[3]) << 010) +
static_cast<uint32_t>(result[4]));
static_cast<uint32_t>(result[4]);
CHECK(restored == i);
// roundtrip
@ -647,14 +647,14 @@ TEST_CASE("MessagePack")
// check individual bytes
CHECK(result[0] == 0xcf);
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
(static_cast<uint64_t>(result[2]) << 060) +
(static_cast<uint64_t>(result[3]) << 050) +
(static_cast<uint64_t>(result[4]) << 040) +
(static_cast<uint64_t>(result[5]) << 030) +
(static_cast<uint64_t>(result[6]) << 020) +
(static_cast<uint64_t>(result[7]) << 010) +
static_cast<uint64_t>(result[8]));
static_cast<uint64_t>(result[8]);
CHECK(restored == i);
// roundtrip

View file

@ -412,17 +412,17 @@ TEST_CASE("regression tests")
class CommaDecimalSeparator : public std::numpunct<char>
{
protected:
char do_decimal_point() const
char do_decimal_point() const override
{
return ',';
}
char do_thousands_sep() const
char do_thousands_sep() const override
{
return '.';
}
std::string do_grouping() const
std::string do_grouping() const override
{
return "\03";
}
@ -755,7 +755,7 @@ TEST_CASE("regression tests")
};
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");
"[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0x98");
// related test case: nonempty UTF-8 string (indefinite length)
std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61};
@ -808,7 +808,7 @@ TEST_CASE("regression tests")
};
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");
"[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xb4");
// related test case: double-precision
std::vector<uint8_t> vec2
@ -822,7 +822,7 @@ TEST_CASE("regression tests")
};
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");
"[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xb4");
}
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")