1 /* 2 __ _____ _____ _____ 3 __| | __| | | | JSON for Modern C++ (test suite) 4 | | |__ | | | | | | version 3.10.4 5 |_____|_____|_____|_|___| https://github.com/nlohmann/json 6 7 Licensed under the MIT License <http://opensource.org/licenses/MIT>. 8 SPDX-License-Identifier: MIT 9 Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>. 10 11 Permission is hereby granted, free of charge, to any person obtaining a copy 12 of this software and associated documentation files (the "Software"), to deal 13 in the Software without restriction, including without limitation the rights 14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 copies of the Software, and to permit persons to whom the Software is 16 furnished to do so, subject to the following conditions: 17 18 The above copyright notice and this permission notice shall be included in all 19 copies or substantial portions of the Software. 20 21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 SOFTWARE. 28 */ 29 30 #include "doctest_compatibility.h" 31 32 // for some reason including this after the json header leads to linker errors with VS 2017... 33 #include <locale> 34 35 #define JSON_TESTS_PRIVATE 36 #include <nlohmann/json.hpp> 37 using nlohmann::json; 38 39 #include <fstream> 40 #include <sstream> 41 #include <list> 42 #include <cstdio> 43 #include <test_data.hpp> 44 45 #if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 46 #define JSON_HAS_CPP_17 47 #endif 48 49 #ifdef JSON_HAS_CPP_17 50 #include <variant> 51 #endif 52 53 #include "fifo_map.hpp" 54 55 ///////////////////////////////////////////////////////////////////// 56 // for #972 57 ///////////////////////////////////////////////////////////////////// 58 59 template<class K, class V, class dummy_compare, class A> 60 using my_workaround_fifo_map = nlohmann::fifo_map<K, V, nlohmann::fifo_map_compare<K>, A>; 61 using my_json = nlohmann::basic_json<my_workaround_fifo_map>; 62 63 ///////////////////////////////////////////////////////////////////// 64 // for #977 65 ///////////////////////////////////////////////////////////////////// 66 67 namespace ns 68 { 69 struct foo 70 { 71 int x; 72 }; 73 74 template <typename, typename SFINAE = void> 75 struct foo_serializer; 76 77 template<typename T> 78 struct foo_serializer<T, typename std::enable_if<std::is_same<foo, T>::value>::type> 79 { 80 template <typename BasicJsonType> to_jsonns::foo_serializer81 static void to_json(BasicJsonType& j, const T& value) 82 { 83 j = BasicJsonType{{"x", value.x}}; 84 } 85 template <typename BasicJsonType> from_jsonns::foo_serializer86 static void from_json(const BasicJsonType& j, T& value) // !!! 87 { 88 nlohmann::from_json(j.at("x"), value.x); 89 } 90 }; 91 92 template<typename T> 93 struct foo_serializer < T, typename std::enable_if < !std::is_same<foo, T>::value >::type > 94 { 95 template <typename BasicJsonType> to_jsonns::foo_serializer96 static void to_json(BasicJsonType& j, const T& value) noexcept // NOLINT(bugprone-exception-escape) 97 { 98 ::nlohmann::to_json(j, value); 99 } 100 template <typename BasicJsonType> from_jsonns::foo_serializer101 static void from_json(const BasicJsonType& j, T& value) //!!! 102 { 103 ::nlohmann::from_json(j, value); 104 } 105 }; 106 } // namespace ns 107 108 using foo_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, 109 std::uint64_t, double, std::allocator, ns::foo_serializer, std::vector<std::uint8_t>>; 110 111 ///////////////////////////////////////////////////////////////////// 112 // for #805 113 ///////////////////////////////////////////////////////////////////// 114 115 namespace 116 { 117 struct nocopy // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) 118 { 119 nocopy() = default; 120 nocopy(const nocopy&) = delete; 121 nocopy(nocopy&&) = delete; 122 nocopy& operator=(const nocopy&) = delete; 123 nocopy& operator=(nocopy&&) = delete; 124 125 int val = 0; 126 to_json(json & j,const nocopy & n)127 friend void to_json(json& j, const nocopy& n) 128 { 129 j = {{"val", n.val}}; 130 } 131 }; 132 } // namespace 133 134 TEST_CASE("regression tests 1") 135 { 136 SECTION("issue #60 - Double quotation mark is not parsed correctly") 137 { 138 SECTION("escape_doublequote") 139 { 140 const auto* s = R"(["\"foo\""])"; 141 json j = json::parse(s); 142 auto expected = R"(["\"foo\""])"_json; 143 CHECK(j == expected); 144 } 145 } 146 147 SECTION("issue #70 - Handle infinity and NaN cases") 148 { 149 // previously, NAN/INFINITY created a null value; now, the values are 150 // properly stored, but are dumped as "null" 151 SECTION("NAN value") 152 { 153 CHECK(json(NAN).dump() == "null"); 154 CHECK(json(json::number_float_t(NAN)).dump() == "null"); 155 } 156 157 SECTION("infinity") 158 { 159 CHECK(json(INFINITY).dump() == "null"); 160 CHECK(json(json::number_float_t(INFINITY)).dump() == "null"); 161 } 162 163 // With 3.0.0, the semantics of this changed: NAN and infinity are 164 // stored properly inside the JSON value (no exception or conversion 165 // to null), but are serialized as null. 166 SECTION("NAN value") 167 { 168 json j1 = NAN; 169 CHECK(j1.is_number_float()); 170 json::number_float_t f1{j1}; 171 CHECK(std::isnan(f1)); 172 173 json j2 = json::number_float_t(NAN); 174 CHECK(j2.is_number_float()); 175 json::number_float_t f2{j2}; 176 CHECK(std::isnan(f2)); 177 } 178 179 SECTION("infinity") 180 { 181 json j1 = INFINITY; 182 CHECK(j1.is_number_float()); 183 json::number_float_t f1{j1}; 184 CHECK(!std::isfinite(f1)); 185 186 json j2 = json::number_float_t(INFINITY); 187 CHECK(j2.is_number_float()); 188 json::number_float_t f2{j2}; 189 CHECK(!std::isfinite(f2)); 190 } 191 } 192 193 SECTION("pull request #71 - handle enum type") 194 { 195 enum { t = 0, u = 102}; 196 json j = json::array(); 197 j.push_back(t); 198 199 // maybe this is not the place to test this? 200 json j2 = u; 201 202 auto anon_enum_value = j2.get<decltype(u)>(); 203 CHECK(u == anon_enum_value); 204 205 // check if the actual value was stored 206 CHECK(j2 == 102); 207 208 static_assert(std::is_same<decltype(anon_enum_value), decltype(u)>::value, ""); 209 210 j.push_back(json::object( 211 { 212 {"game_type", t} 213 })); 214 } 215 216 SECTION("issue #76 - dump() / parse() not idempotent") 217 { 218 // create JSON object 219 json fields; 220 fields["one"] = std::string("one"); 221 fields["two"] = std::string("two three"); 222 fields["three"] = std::string("three \"four\""); 223 224 // create another JSON object by deserializing the serialization 225 std::string payload = fields.dump(); 226 json parsed_fields = json::parse(payload); 227 228 // check individual fields to match both objects 229 CHECK(parsed_fields["one"] == fields["one"]); 230 CHECK(parsed_fields["two"] == fields["two"]); 231 CHECK(parsed_fields["three"] == fields["three"]); 232 233 // check individual fields to match original input 234 CHECK(parsed_fields["one"] == std::string("one")); 235 CHECK(parsed_fields["two"] == std::string("two three")); 236 CHECK(parsed_fields["three"] == std::string("three \"four\"")); 237 238 // check equality of the objects 239 CHECK(parsed_fields == fields); 240 241 // check equality of the serialized objects 242 CHECK(fields.dump() == parsed_fields.dump()); 243 244 // check everything in one line 245 CHECK(fields == json::parse(fields.dump())); 246 } 247 248 SECTION("issue #82 - lexer::get_number return NAN") 249 { 250 const auto* const content = R"( 251 { 252 "Test":"Test1", 253 "Number":100, 254 "Foo":42.42 255 })"; 256 257 std::stringstream ss; 258 ss << content; 259 json j; 260 ss >> j; 261 262 auto test = j["Test"].get<std::string>(); 263 CHECK(test == "Test1"); 264 int number{j["Number"]}; 265 CHECK(number == 100); 266 float foo{j["Foo"]}; 267 CHECK(static_cast<double>(foo) == Approx(42.42)); 268 } 269 270 SECTION("issue #89 - nonstandard integer type") 271 { 272 // create JSON class with nonstandard integer number type 273 using custom_json = 274 nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float>; 275 custom_json j; 276 j["int_1"] = 1; 277 CHECK(j["int_1"] == 1); 278 279 // tests for correct handling of non-standard integers that overflow the type selected by the user 280 281 // unsigned integer object creation - expected to wrap and still be stored as an integer 282 j = 4294967296U; // 2^32 283 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_unsigned)); 284 CHECK(j.get<uint32_t>() == 0); // Wrap 285 286 // unsigned integer parsing - expected to overflow and be stored as a float 287 j = custom_json::parse("4294967296"); // 2^32 288 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float)); 289 CHECK(j.get<float>() == 4294967296.0f); 290 291 // integer object creation - expected to wrap and still be stored as an integer 292 j = -2147483649LL; // -2^31-1 293 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_integer)); 294 CHECK(j.get<int32_t>() == 2147483647); // Wrap 295 296 // integer parsing - expected to overflow and be stored as a float with rounding 297 j = custom_json::parse("-2147483649"); // -2^31 298 CHECK(static_cast<int>(j.type()) == static_cast<int>(custom_json::value_t::number_float)); 299 CHECK(j.get<float>() == -2147483650.0f); 300 } 301 302 SECTION("issue #93 reverse_iterator operator inheritance problem") 303 { 304 { 305 json a = {1, 2, 3}; 306 json::reverse_iterator rit = a.rbegin(); 307 ++rit; 308 CHECK(*rit == json(2)); 309 CHECK(rit.value() == json(2)); 310 } 311 { 312 json a = {1, 2, 3}; 313 json::reverse_iterator rit = ++a.rbegin(); 314 CHECK(*rit == json(2)); 315 CHECK(rit.value() == json(2)); 316 } 317 { 318 json a = {1, 2, 3}; 319 json::reverse_iterator rit = a.rbegin(); 320 ++rit; 321 json b = {0, 0, 0}; 322 std::transform(rit, a.rend(), b.rbegin(), [](json el) __anon1124f2ca0302(json el) 323 { 324 return el; 325 }); 326 CHECK(b == json({0, 1, 2})); 327 } 328 { 329 json a = {1, 2, 3}; 330 json b = {0, 0, 0}; 331 std::transform(++a.rbegin(), a.rend(), b.rbegin(), [](json el) __anon1124f2ca0402(json el) 332 { 333 return el; 334 }); 335 CHECK(b == json({0, 1, 2})); 336 } 337 } 338 339 SECTION("issue #100 - failed to iterator json object with reverse_iterator") 340 { 341 json config = 342 { 343 { "111", 111 }, 344 { "112", 112 }, 345 { "113", 113 } 346 }; 347 348 std::stringstream ss; 349 350 for (auto it = config.begin(); it != config.end(); ++it) 351 { 352 ss << it.key() << ": " << it.value() << '\n'; 353 } 354 355 for (auto it = config.rbegin(); it != config.rend(); ++it) 356 { 357 ss << it.key() << ": " << it.value() << '\n'; 358 } 359 360 CHECK(ss.str() == "111: 111\n112: 112\n113: 113\n113: 113\n112: 112\n111: 111\n"); 361 } 362 363 SECTION("issue #101 - binary string causes numbers to be dumped as hex") 364 { 365 int64_t number = 10; 366 std::string bytes{"\x00" "asdf\n", 6}; 367 json j; 368 j["int64"] = number; 369 j["binary string"] = bytes; 370 // make sure the number is really printed as decimal "10" and not as 371 // hexadecimal "a" 372 CHECK(j.dump() == "{\"binary string\":\"\\u0000asdf\\n\",\"int64\":10}"); 373 } 374 375 SECTION("issue #111 - subsequent unicode chars") 376 { 377 std::string bytes{0x7, 0x7}; 378 json j; 379 j["string"] = bytes; 380 CHECK(j["string"] == "\u0007\u0007"); 381 } 382 383 #if JSON_USE_IMPLICIT_CONVERSIONS 384 SECTION("issue #144 - implicit assignment to std::string fails") 385 { 386 json o = {{"name", "value"}}; 387 388 std::string s1 = o["name"]; 389 CHECK(s1 == "value"); 390 391 std::string s2; 392 s2 = o["name"]; 393 394 CHECK(s2 == "value"); 395 396 // improve coverage 397 o["int"] = 1; 398 CHECK_THROWS_AS(s2 = o["int"], json::type_error); 399 #if JSON_DIAGNOSTICS 400 CHECK_THROWS_WITH(s2 = o["int"], "[json.exception.type_error.302] (/int) type must be string, but is number"); 401 #else 402 CHECK_THROWS_WITH(s2 = o["int"], "[json.exception.type_error.302] type must be string, but is number"); 403 #endif 404 } 405 #endif 406 407 SECTION("issue #146 - character following a surrogate pair is skipped") 408 { 409 CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == "\xf0\x93\x81\xa0\x61\x62\x63"); 410 } 411 412 SECTION("issue #171 - Cannot index by key of type static constexpr const char*") 413 { 414 json j; 415 416 // Non-const access with key as "char []" 417 char array_key[] = "Key1"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 418 CHECK_NOTHROW(j[array_key] = 1); 419 CHECK(j[array_key] == json(1)); 420 421 // Non-const access with key as "const char[]" 422 const char const_array_key[] = "Key2"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 423 CHECK_NOTHROW(j[const_array_key] = 2); 424 CHECK(j[const_array_key] == json(2)); 425 426 // Non-const access with key as "char *" 427 char _ptr_key[] = "Key3"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 428 char* ptr_key = &_ptr_key[0]; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) 429 CHECK_NOTHROW(j[ptr_key] = 3); 430 CHECK(j[ptr_key] == json(3)); 431 432 // Non-const access with key as "const char *" 433 const char* const_ptr_key = "Key4"; 434 CHECK_NOTHROW(j[const_ptr_key] = 4); 435 CHECK(j[const_ptr_key] == json(4)); 436 437 // Non-const access with key as "static constexpr const char *" 438 static constexpr const char* constexpr_ptr_key = "Key5"; 439 CHECK_NOTHROW(j[constexpr_ptr_key] = 5); 440 CHECK(j[constexpr_ptr_key] == json(5)); 441 442 const json j_const = j; 443 444 // Const access with key as "char []" 445 CHECK(j_const[array_key] == json(1)); 446 447 // Const access with key as "const char[]" 448 CHECK(j_const[const_array_key] == json(2)); 449 450 // Const access with key as "char *" 451 CHECK(j_const[ptr_key] == json(3)); 452 453 // Const access with key as "const char *" 454 CHECK(j_const[const_ptr_key] == json(4)); 455 456 // Const access with key as "static constexpr const char *" 457 CHECK(j_const[constexpr_ptr_key] == json(5)); 458 } 459 460 SECTION("issue #186 miloyip/nativejson-benchmark: floating-point parsing") 461 { 462 json j; 463 464 j = json::parse("-0.0"); 465 CHECK(j.get<double>() == -0.0); 466 467 j = json::parse("2.22507385850720113605740979670913197593481954635164564e-308"); 468 CHECK(j.get<double>() == 2.2250738585072009e-308); 469 470 j = json::parse("0.999999999999999944488848768742172978818416595458984374"); 471 CHECK(j.get<double>() == 0.99999999999999989); 472 473 j = json::parse("1.00000000000000011102230246251565404236316680908203126"); 474 CHECK(j.get<double>() == 1.00000000000000022); 475 476 j = json::parse("7205759403792793199999e-5"); 477 CHECK(j.get<double>() == 72057594037927928.0); 478 479 j = json::parse("922337203685477529599999e-5"); 480 CHECK(j.get<double>() == 9223372036854774784.0); 481 482 j = json::parse("1014120480182583464902367222169599999e-5"); 483 CHECK(j.get<double>() == 10141204801825834086073718800384.0); 484 485 j = json::parse("5708990770823839207320493820740630171355185151999e-3"); 486 CHECK(j.get<double>() == 5708990770823838890407843763683279797179383808.0); 487 488 // create JSON class with nonstandard float number type 489 490 // float 491 nlohmann::basic_json<std::map, std::vector, std::string, bool, int32_t, uint32_t, float> j_float = 492 1.23e25f; 493 CHECK(j_float.get<float>() == 1.23e25f); 494 495 // double 496 nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double> j_double = 497 1.23e35; 498 CHECK(j_double.get<double>() == 1.23e35); 499 500 // long double 501 nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, long double> 502 j_long_double = 1.23e45L; 503 CHECK(j_long_double.get<long double>() == 1.23e45L); 504 } 505 506 SECTION("issue #228 - double values are serialized with commas as decimal points") 507 { 508 json j1a = 2312.42; 509 json j1b = json::parse("2312.42"); 510 511 json j2a = 2342e-2; 512 //issue #230 513 //json j2b = json::parse("2342e-2"); 514 515 json j3a = 10E3; 516 json j3b = json::parse("10E3"); 517 json j3c = json::parse("10e3"); 518 519 // class to create a locale that would use a comma for decimals 520 class CommaDecimalSeparator : public std::numpunct<char> 521 { 522 protected: do_decimal_point() const523 char do_decimal_point() const override 524 { 525 return ','; 526 } 527 do_thousands_sep() const528 char do_thousands_sep() const override 529 { 530 return '.'; 531 } 532 do_grouping() const533 std::string do_grouping() const override 534 { 535 return "\03"; 536 } 537 }; 538 539 // change locale to mess with decimal points 540 auto orig_locale = std::locale::global(std::locale(std::locale(), new CommaDecimalSeparator)); 541 542 CHECK(j1a.dump() == "2312.42"); 543 CHECK(j1b.dump() == "2312.42"); 544 545 // check if locale is properly reset 546 std::stringstream ss; 547 ss.imbue(std::locale(std::locale(), new CommaDecimalSeparator)); 548 ss << 4712.11; 549 CHECK(ss.str() == "4.712,11"); 550 ss << j1a; 551 CHECK(ss.str() == "4.712,112312.42"); 552 ss << 47.11; 553 CHECK(ss.str() == "4.712,112312.4247,11"); 554 555 CHECK(j2a.dump() == "23.42"); 556 //issue #230 557 //CHECK(j2b.dump() == "23.42"); 558 559 CHECK(j3a.dump() == "10000.0"); 560 CHECK(j3b.dump() == "10000.0"); 561 CHECK(j3c.dump() == "10000.0"); 562 //CHECK(j3b.dump() == "1E04"); // roundtrip error 563 //CHECK(j3c.dump() == "1e04"); // roundtrip error 564 565 std::locale::global(orig_locale); 566 } 567 568 SECTION("issue #378 - locale-independent num-to-str") 569 { 570 setlocale(LC_NUMERIC, "de_DE.UTF-8"); 571 572 // verify that dumped correctly with '.' and no grouping 573 const json j1 = 12345.67; 574 CHECK(json(12345.67).dump() == "12345.67"); 575 setlocale(LC_NUMERIC, "C"); 576 } 577 578 SECTION("issue #379 - locale-independent str-to-num") 579 { 580 setlocale(LC_NUMERIC, "de_DE.UTF-8"); 581 582 // verify that parsed correctly despite using strtod internally 583 CHECK(json::parse("3.14").get<double>() == 3.14); 584 585 // check a different code path 586 CHECK(json::parse("1.000000000000000000000000000000000000000000000000000000000000000000000000").get<double>() == 1.0); 587 } 588 589 SECTION("issue #233 - Can't use basic_json::iterator as a base iterator for std::move_iterator") 590 { 591 json source = {"a", "b", "c"}; 592 json expected = {"a", "b"}; 593 json dest; 594 595 std::copy_n(std::make_move_iterator(source.begin()), 2, std::back_inserter(dest)); 596 597 CHECK(dest == expected); 598 } 599 600 SECTION("issue #235 - ambiguous overload for 'push_back' and 'operator+='") 601 { 602 json data = {{"key", "value"}}; 603 data.push_back({"key2", "value2"}); 604 data += {"key3", "value3"}; 605 606 CHECK(data == json({{"key", "value"}, {"key2", "value2"}, {"key3", "value3"}})); 607 } 608 609 SECTION("issue #269 - diff generates incorrect patch when removing multiple array elements") 610 { 611 json doc = R"( { "arr1": [1, 2, 3, 4] } )"_json; 612 json expected = R"( { "arr1": [1, 2] } )"_json; 613 614 // check roundtrip 615 CHECK(doc.patch(json::diff(doc, expected)) == expected); 616 } 617 618 SECTION("issue #283 - value() does not work with _json_pointer types") 619 { 620 json j = 621 { 622 {"object", {{"key1", 1}, {"key2", 2}}}, 623 }; 624 625 int at_integer{j.at("/object/key2"_json_pointer)}; 626 int val_integer = j.value("/object/key2"_json_pointer, 0); 627 628 CHECK(at_integer == val_integer); 629 } 630 631 SECTION("issue #304 - Unused variable warning") 632 { 633 // code triggered a "warning: unused variable" warning and is left 634 // here to avoid the warning in the future 635 json object; 636 json patch = json::array(); 637 object = object.patch(patch); 638 } 639 640 SECTION("issue #306 - Parsing fails without space at end of file") 641 { 642 for (const auto* filename : 643 { 644 TEST_DATA_DIRECTORY "/regression/broken_file.json", 645 TEST_DATA_DIRECTORY "/regression/working_file.json" 646 }) 647 { 648 CAPTURE(filename) 649 json j; 650 std::ifstream f(filename); 651 CHECK_NOTHROW(f >> j); 652 } 653 } 654 655 SECTION("issue #310 - make json_benchmarks no longer working in 2.0.4") 656 { 657 for (const auto* filename : 658 { 659 TEST_DATA_DIRECTORY "/regression/floats.json", 660 TEST_DATA_DIRECTORY "/regression/signed_ints.json", 661 TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", 662 TEST_DATA_DIRECTORY "/regression/small_signed_ints.json" 663 }) 664 { 665 CAPTURE(filename) 666 json j; 667 std::ifstream f(filename); 668 CHECK_NOTHROW(f >> j); 669 } 670 } 671 672 SECTION("issue #323 - add nested object capabilities to pointers") 673 { 674 json j; 675 j["/this/that/2"_json_pointer] = 27; 676 CHECK(j == json({{"this", {{"that", {nullptr, nullptr, 27}}}}})); 677 } 678 679 SECTION("issue #329 - serialized value not always can be parsed") 680 { 681 json _; 682 CHECK_THROWS_AS(_ = json::parse("22e2222"), json::out_of_range&); 683 CHECK_THROWS_WITH(_ = json::parse("22e2222"), 684 "[json.exception.out_of_range.406] number overflow parsing '22e2222'"); 685 } 686 687 SECTION("issue #360 - Loss of precision when serializing <double>") 688 { 689 auto check_roundtrip = [](double number) __anon1124f2ca0502(double number) 690 { 691 CAPTURE(number) 692 693 json j = number; 694 CHECK(j.is_number_float()); 695 696 std::stringstream ss; 697 ss << j; 698 699 CHECK_NOTHROW(ss >> j); 700 CHECK(j.is_number_float()); 701 CHECK(j.get<json::number_float_t>() == number); 702 }; 703 704 check_roundtrip(100000000000.1236); 705 check_roundtrip((std::numeric_limits<json::number_float_t>::max)()); 706 707 // Some more numbers which fail to roundtrip when serialized with digits10 significand digits (instead of max_digits10) 708 check_roundtrip(1.541888611948064e-17); 709 check_roundtrip(5.418771028591015e-16); 710 check_roundtrip(9.398685592608595e-15); 711 check_roundtrip(8.826843952762347e-14); 712 check_roundtrip(8.143291313475335e-13); 713 check_roundtrip(4.851328172762508e-12); 714 check_roundtrip(6.677850998084358e-11); 715 check_roundtrip(3.995398518174525e-10); 716 check_roundtrip(1.960452605645124e-9); 717 check_roundtrip(3.551812586302883e-8); 718 check_roundtrip(2.947988411689261e-7); 719 check_roundtrip(8.210166748056192e-6); 720 check_roundtrip(6.104889704266753e-5); 721 check_roundtrip(0.0008629954631330876); 722 check_roundtrip(0.004936993881051611); 723 check_roundtrip(0.08309725102608073); 724 check_roundtrip(0.5210494268499783); 725 check_roundtrip(6.382927930939767); 726 check_roundtrip(59.94947245358671); 727 check_roundtrip(361.0838651266122); 728 check_roundtrip(4678.354596181877); 729 check_roundtrip(61412.17658956043); 730 check_roundtrip(725696.0799057782); 731 check_roundtrip(2811732.583399828); 732 check_roundtrip(30178351.07533605); 733 check_roundtrip(689684880.3235844); 734 check_roundtrip(5714887673.555147); 735 check_roundtrip(84652038821.18808); 736 check_roundtrip(156510583431.7721); 737 check_roundtrip(5938450569021.732); 738 check_roundtrip(83623297654460.33); 739 check_roundtrip(701466573254773.6); 740 check_roundtrip(1369013370304513); 741 check_roundtrip(96963648023094720); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) 742 check_roundtrip(3.478237409280108e+17); 743 } 744 745 SECTION("issue #366 - json::parse on failed stream gets stuck") 746 { 747 std::ifstream f("file_not_found.json"); 748 json _; 749 CHECK_THROWS_AS(_ = json::parse(f), json::parse_error&); 750 CHECK_THROWS_WITH(_ = json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 751 } 752 753 SECTION("issue #367 - calling stream at EOF") 754 { 755 std::stringstream ss; 756 json j; 757 ss << "123"; 758 CHECK_NOTHROW(ss >> j); 759 760 // see https://github.com/nlohmann/json/issues/367#issuecomment-262841893: 761 // ss is not at EOF; this yielded an error before the fix 762 // (threw basic_string::append). No, it should just throw 763 // a parse error because of the EOF. 764 CHECK_THROWS_AS(ss >> j, json::parse_error&); 765 CHECK_THROWS_WITH(ss >> j, 766 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 767 } 768 769 SECTION("issue #367 - behavior of operator>> should more closely resemble that of built-in overloads") 770 { 771 SECTION("(empty)") 772 { 773 std::stringstream ss; 774 json j; 775 CHECK_THROWS_AS(ss >> j, json::parse_error&); 776 CHECK_THROWS_WITH(ss >> j, 777 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 778 } 779 780 SECTION("(whitespace)") 781 { 782 std::stringstream ss; 783 ss << " "; 784 json j; 785 CHECK_THROWS_AS(ss >> j, json::parse_error&); 786 CHECK_THROWS_WITH(ss >> j, 787 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 788 } 789 790 SECTION("one value") 791 { 792 std::stringstream ss; 793 ss << "111"; 794 json j; 795 CHECK_NOTHROW(ss >> j); 796 CHECK(j == 111); 797 798 CHECK_THROWS_AS(ss >> j, json::parse_error&); 799 CHECK_THROWS_WITH(ss >> j, 800 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 801 } 802 803 SECTION("one value + whitespace") 804 { 805 std::stringstream ss; 806 ss << "222 \t\n"; 807 json j; 808 CHECK_NOTHROW(ss >> j); 809 CHECK(j == 222); 810 811 CHECK_THROWS_AS(ss >> j, json::parse_error&); 812 CHECK_THROWS_WITH(ss >> j, 813 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 814 } 815 816 SECTION("whitespace + one value") 817 { 818 std::stringstream ss; 819 ss << "\n\t 333"; 820 json j; 821 CHECK_NOTHROW(ss >> j); 822 CHECK(j == 333); 823 824 CHECK_THROWS_AS(ss >> j, json::parse_error&); 825 CHECK_THROWS_WITH(ss >> j, 826 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 827 } 828 829 SECTION("three values") 830 { 831 std::stringstream ss; 832 ss << " 111 \n222\n \n 333"; 833 json j; 834 CHECK_NOTHROW(ss >> j); 835 CHECK(j == 111); 836 CHECK_NOTHROW(ss >> j); 837 CHECK(j == 222); 838 CHECK_NOTHROW(ss >> j); 839 CHECK(j == 333); 840 841 CHECK_THROWS_AS(ss >> j, json::parse_error&); 842 CHECK_THROWS_WITH(ss >> j, 843 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 844 } 845 846 SECTION("literals without whitespace") 847 { 848 std::stringstream ss; 849 ss << "truefalsenull\"\""; 850 json j; 851 CHECK_NOTHROW(ss >> j); 852 CHECK(j == true); 853 CHECK_NOTHROW(ss >> j); 854 CHECK(j == false); 855 CHECK_NOTHROW(ss >> j); 856 CHECK(j == nullptr); 857 CHECK_NOTHROW(ss >> j); 858 CHECK(j == ""); 859 860 CHECK_THROWS_AS(ss >> j, json::parse_error&); 861 CHECK_THROWS_WITH(ss >> j, 862 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 863 } 864 865 SECTION("example from #529") 866 { 867 std::stringstream ss; 868 ss << "{\n \"one\" : 1,\n \"two\" : 2\n}\n{\n \"three\" : 3\n}"; 869 json j; 870 CHECK_NOTHROW(ss >> j); 871 CHECK(j == json({{"one", 1}, {"two", 2}})); 872 CHECK_NOTHROW(ss >> j); 873 CHECK(j == json({{"three", 3}})); 874 875 CHECK_THROWS_AS(ss >> j, json::parse_error&); 876 CHECK_THROWS_WITH(ss >> j, 877 "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); 878 } 879 880 SECTION("second example from #529") 881 { 882 std::string str = "{\n\"one\" : 1,\n\"two\" : 2\n}\n{\n\"three\" : 3\n}"; 883 884 { 885 std::ofstream file("test.json"); 886 file << str; 887 } 888 889 std::ifstream stream("test.json", std::ifstream::in); 890 json val; 891 892 size_t i = 0; 893 while (stream.peek() != EOF) 894 { 895 CAPTURE(i) 896 CHECK_NOTHROW(stream >> val); 897 898 CHECK(i < 2); 899 900 if (i == 0) 901 { 902 CHECK(val == json({{"one", 1}, {"two", 2}})); 903 } 904 905 if (i == 1) 906 { 907 CHECK(val == json({{"three", 3}})); 908 } 909 910 ++i; 911 } 912 913 std::remove("test.json"); 914 } 915 } 916 917 SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)") 918 { 919 // original test case 920 json j1 = json::parse("-9223372036854775808"); 921 CHECK(j1.is_number_integer()); 922 CHECK(j1.get<json::number_integer_t>() == INT64_MIN); 923 924 // edge case (+1; still an integer) 925 json j2 = json::parse("-9223372036854775807"); 926 CHECK(j2.is_number_integer()); 927 CHECK(j2.get<json::number_integer_t>() == INT64_MIN + 1); 928 929 // edge case (-1; overflow -> floats) 930 json j3 = json::parse("-9223372036854775809"); 931 CHECK(j3.is_number_float()); 932 } 933 934 SECTION("issue #380 - bug in overflow detection when parsing integers") 935 { 936 json j = json::parse("166020696663385964490"); 937 CHECK(j.is_number_float()); 938 CHECK(j.get<json::number_float_t>() == 166020696663385964490.0); 939 } 940 941 SECTION("issue #405 - Heap-buffer-overflow (OSS-Fuzz issue 342)") 942 { 943 // original test case 944 std::vector<uint8_t> vec {0x65, 0xf5, 0x0a, 0x48, 0x21}; 945 json _; 946 CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&); 947 CHECK_THROWS_WITH(_ = json::from_cbor(vec), 948 "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing CBOR string: unexpected end of input"); 949 } 950 951 SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)") 952 { 953 json _; 954 955 // original test case: incomplete float64 956 std::vector<uint8_t> vec1 {0xcb, 0x8f, 0x0a}; 957 CHECK_THROWS_AS(_ = json::from_msgpack(vec1), json::parse_error&); 958 CHECK_THROWS_WITH(_ = json::from_msgpack(vec1), 959 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input"); 960 961 // related test case: incomplete float32 962 std::vector<uint8_t> vec2 {0xca, 0x8f, 0x0a}; 963 CHECK_THROWS_AS(_ = json::from_msgpack(vec2), json::parse_error&); 964 CHECK_THROWS_WITH(_ = json::from_msgpack(vec2), 965 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing MessagePack number: unexpected end of input"); 966 967 // related test case: incomplete Half-Precision Float (CBOR) 968 std::vector<uint8_t> vec3 {0xf9, 0x8f}; 969 CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&); 970 CHECK_THROWS_WITH(_ = json::from_cbor(vec3), 971 "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR number: unexpected end of input"); 972 973 // related test case: incomplete Single-Precision Float (CBOR) 974 std::vector<uint8_t> vec4 {0xfa, 0x8f, 0x0a}; 975 CHECK_THROWS_AS(_ = json::from_cbor(vec4), json::parse_error&); 976 CHECK_THROWS_WITH(_ = json::from_cbor(vec4), 977 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input"); 978 979 // related test case: incomplete Double-Precision Float (CBOR) 980 std::vector<uint8_t> vec5 {0xfb, 0x8f, 0x0a}; 981 CHECK_THROWS_AS(_ = json::from_cbor(vec5), json::parse_error&); 982 CHECK_THROWS_WITH(_ = json::from_cbor(vec5), 983 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR number: unexpected end of input"); 984 } 985 986 SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)") 987 { 988 json _; 989 990 // original test case 991 std::vector<uint8_t> vec1 {0x87}; 992 CHECK_THROWS_AS(_ = json::from_msgpack(vec1), json::parse_error&); 993 CHECK_THROWS_WITH(_ = json::from_msgpack(vec1), 994 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input"); 995 996 // more test cases for MessagePack 997 for (auto b : 998 { 999 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, // fixmap 1000 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, // fixarray 1001 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, // fixstr 1002 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf 1003 }) 1004 { 1005 std::vector<uint8_t> vec(1, static_cast<uint8_t>(b)); 1006 CHECK_THROWS_AS(_ = json::from_msgpack(vec), json::parse_error&); 1007 } 1008 1009 // more test cases for CBOR 1010 for (auto b : 1011 { 1012 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 1013 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, // UTF-8 string 1014 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 1015 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, // array 1016 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 1017 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7 // map 1018 }) 1019 { 1020 std::vector<uint8_t> vec(1, static_cast<uint8_t>(b)); 1021 CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&); 1022 } 1023 1024 // special case: empty input 1025 std::vector<uint8_t> vec2; 1026 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&); 1027 CHECK_THROWS_WITH(_ = json::from_cbor(vec2), 1028 "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing CBOR value: unexpected end of input"); 1029 CHECK_THROWS_AS(_ = json::from_msgpack(vec2), json::parse_error&); 1030 CHECK_THROWS_WITH(_ = json::from_msgpack(vec2), 1031 "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing MessagePack value: unexpected end of input"); 1032 } 1033 1034 SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)") 1035 { 1036 json _; 1037 1038 // original test case: empty UTF-8 string (indefinite length) 1039 std::vector<uint8_t> vec1 {0x7f}; 1040 CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&); 1041 CHECK_THROWS_WITH(_ = json::from_cbor(vec1), 1042 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input"); 1043 1044 // related test case: empty array (indefinite length) 1045 std::vector<uint8_t> vec2 {0x9f}; 1046 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&); 1047 CHECK_THROWS_WITH(_ = json::from_cbor(vec2), 1048 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR value: unexpected end of input"); 1049 1050 // related test case: empty map (indefinite length) 1051 std::vector<uint8_t> vec3 {0xbf}; 1052 CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&); 1053 CHECK_THROWS_WITH(_ = json::from_cbor(vec3), 1054 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input"); 1055 } 1056 1057 SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)") 1058 { 1059 // original test case 1060 std::vector<uint8_t> vec 1061 { 1062 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 1063 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, 1064 0x60, 0xab, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 1065 0x98, 0x98, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, 1066 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1067 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1068 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1069 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1070 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1071 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1072 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xa0, 0x9f, 1073 0x9f, 0x97, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1074 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1075 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1076 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1077 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 1078 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60 1079 }; 1080 1081 json _; 1082 CHECK_THROWS_AS(_ = json::from_cbor(vec), json::parse_error&); 1083 CHECK_THROWS_WITH(_ = json::from_cbor(vec), 1084 "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x98"); 1085 1086 // related test case: nonempty UTF-8 string (indefinite length) 1087 std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61}; 1088 CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&); 1089 CHECK_THROWS_WITH(_ = json::from_cbor(vec1), 1090 "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing CBOR string: unexpected end of input"); 1091 1092 // related test case: nonempty array (indefinite length) 1093 std::vector<uint8_t> vec2 {0x9f, 0x01}; 1094 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&); 1095 CHECK_THROWS_WITH(_ = json::from_cbor(vec2), 1096 "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing CBOR value: unexpected end of input"); 1097 1098 // related test case: nonempty map (indefinite length) 1099 std::vector<uint8_t> vec3 {0xbf, 0x61, 0x61, 0x01}; 1100 CHECK_THROWS_AS(_ = json::from_cbor(vec3), json::parse_error&); 1101 CHECK_THROWS_WITH(_ = json::from_cbor(vec3), 1102 "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing CBOR string: unexpected end of input"); 1103 } 1104 1105 SECTION("issue #414 - compare with literal 0)") 1106 { 1107 #define CHECK_TYPE(v) \ 1108 CHECK((json(v) == (v)));\ 1109 CHECK(((v) == json(v)));\ 1110 CHECK_FALSE((json(v) != (v)));\ 1111 CHECK_FALSE(((v) != json(v))); 1112 1113 CHECK_TYPE(nullptr) 1114 CHECK_TYPE(0) 1115 CHECK_TYPE(0u) 1116 CHECK_TYPE(0L) 1117 CHECK_TYPE(0.0) 1118 CHECK_TYPE("") // NOLINT(readability-container-size-empty) 1119 1120 #undef CHECK_TYPE 1121 } 1122 1123 SECTION("issue #416 - Use-of-uninitialized-value (OSS-Fuzz issue 377)") 1124 { 1125 // original test case 1126 std::vector<uint8_t> vec1 1127 { 1128 0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 1129 0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 1130 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71, 1131 0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a, 1132 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, 1133 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfa 1134 }; 1135 1136 json _; 1137 CHECK_THROWS_AS(_ = json::from_cbor(vec1), json::parse_error&); 1138 CHECK_THROWS_WITH(_ = json::from_cbor(vec1), 1139 "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4"); 1140 1141 // related test case: double-precision 1142 std::vector<uint8_t> vec2 1143 { 1144 0x94, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 1145 0x3a, 0x96, 0x96, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 1146 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0x71, 1147 0xb4, 0xb4, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0x3a, 1148 0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61, 1149 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb 1150 }; 1151 CHECK_THROWS_AS(_ = json::from_cbor(vec2), json::parse_error&); 1152 CHECK_THROWS_WITH(_ = json::from_cbor(vec2), 1153 "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4"); 1154 } 1155 1156 SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)") 1157 { 1158 std::vector<uint8_t> vec = {'-', '0', '1', '2', '2', '7', '4'}; 1159 json _; 1160 CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&); 1161 } 1162 1163 SECTION("issue #454 - doubles are printed as integers") 1164 { 1165 json j = R"({"bool_value":true,"double_value":2.0,"int_value":10,"level1":{"list_value":[3,"hi",false],"tmp":5.0},"string_value":"hello"})"_json; 1166 CHECK(j["double_value"].is_number_float()); 1167 } 1168 1169 #if JSON_USE_IMPLICIT_CONVERSIONS 1170 SECTION("issue #464 - VS2017 implicit to std::string conversion fix") 1171 { 1172 json v = "test"; 1173 std::string test; 1174 test = v; 1175 CHECK(v == "test"); 1176 } 1177 #endif 1178 1179 SECTION("issue #465 - roundtrip error while parsing 1000000000000000010E5") 1180 { 1181 json j1 = json::parse("1000000000000000010E5"); 1182 std::string s1 = j1.dump(); 1183 json j2 = json::parse(s1); 1184 std::string s2 = j2.dump(); 1185 CHECK(s1 == s2); 1186 } 1187 1188 #if JSON_USE_IMPLICIT_CONVERSIONS 1189 SECTION("issue #473 - inconsistent behavior in conversion to array type") 1190 { 1191 json j_array = {1, 2, 3, 4}; 1192 json j_number = 42; 1193 json j_null = nullptr; 1194 1195 SECTION("std::vector") 1196 { 1197 auto create = [](const json & j) __anon1124f2ca0602(const json & j) 1198 { 1199 std::vector<int> v = j; 1200 }; 1201 1202 CHECK_NOTHROW(create(j_array)); 1203 CHECK_THROWS_AS(create(j_number), json::type_error&); 1204 CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); 1205 CHECK_THROWS_AS(create(j_null), json::type_error&); 1206 CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); 1207 } 1208 1209 SECTION("std::list") 1210 { 1211 auto create = [](const json & j) __anon1124f2ca0702(const json & j) 1212 { 1213 std::list<int> v = j; 1214 }; 1215 1216 CHECK_NOTHROW(create(j_array)); 1217 CHECK_THROWS_AS(create(j_number), json::type_error&); 1218 CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); 1219 CHECK_THROWS_AS(create(j_null), json::type_error&); 1220 CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); 1221 } 1222 1223 SECTION("std::forward_list") 1224 { 1225 auto create = [](const json & j) __anon1124f2ca0802(const json & j) 1226 { 1227 std::forward_list<int> v = j; 1228 }; 1229 1230 CHECK_NOTHROW(create(j_array)); 1231 CHECK_THROWS_AS(create(j_number), json::type_error&); 1232 CHECK_THROWS_WITH(create(j_number), "[json.exception.type_error.302] type must be array, but is number"); 1233 CHECK_THROWS_AS(create(j_null), json::type_error&); 1234 CHECK_THROWS_WITH(create(j_null), "[json.exception.type_error.302] type must be array, but is null"); 1235 } 1236 } 1237 #endif 1238 1239 SECTION("issue #486 - json::value_t can't be a map's key type in VC++ 2015") 1240 { 1241 // the code below must compile with MSVC 1242 std::map<json::value_t, std::string> jsonTypes ; 1243 jsonTypes[json::value_t::array] = "array"; 1244 } 1245 1246 SECTION("issue #494 - conversion from vector<bool> to json fails to build") 1247 { 1248 std::vector<bool> boolVector = {false, true, false, false}; 1249 json j; 1250 j["bool_vector"] = boolVector; 1251 1252 CHECK(j["bool_vector"].dump() == "[false,true,false,false]"); 1253 } 1254 1255 SECTION("issue #504 - assertion error (OSS-Fuzz 856)") 1256 { 1257 std::vector<uint8_t> vec1 = {0xf9, 0xff, 0xff, 0x4a, 0x3a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x37, 0x02, 0x38}; 1258 json j1 = json::from_cbor(vec1, false); 1259 1260 // step 2: round trip 1261 std::vector<uint8_t> vec2 = json::to_cbor(j1); 1262 1263 // parse serialization 1264 json j2 = json::from_cbor(vec2); 1265 1266 // NaN is dumped to "null" 1267 CHECK(j2.is_number_float()); 1268 CHECK(std::isnan(j2.get<json::number_float_t>())); 1269 CHECK(j2.dump() == "null"); 1270 1271 // check if serializations match 1272 CHECK(json::to_cbor(j2) == vec2); 1273 } 1274 1275 SECTION("issue #512 - use of overloaded operator '<=' is ambiguous") 1276 { 1277 json j; 1278 j["a"] = 5; 1279 1280 // json op scalar 1281 CHECK(j["a"] == 5); 1282 CHECK(j["a"] != 4); 1283 1284 CHECK(j["a"] <= 7); 1285 CHECK(j["a"] < 7); 1286 CHECK(j["a"] >= 3); 1287 CHECK(j["a"] > 3); 1288 1289 1290 CHECK(!(j["a"] <= 4)); 1291 CHECK(!(j["a"] < 4)); 1292 CHECK(!(j["a"] >= 6)); 1293 CHECK(!(j["a"] > 6)); 1294 1295 // scalar op json 1296 CHECK(5 == j["a"]); 1297 CHECK(4 != j["a"]); 1298 1299 CHECK(7 >= j["a"]); 1300 CHECK(7 > j["a"]); 1301 CHECK(3 <= j["a"]); 1302 CHECK(3 < j["a"]); 1303 1304 CHECK(!(4 >= j["a"])); 1305 CHECK(!(4 > j["a"])); 1306 CHECK(!(6 <= j["a"])); 1307 CHECK(!(6 < j["a"])); 1308 } 1309 1310 SECTION("issue #575 - heap-buffer-overflow (OSS-Fuzz 1400)") 1311 { 1312 json _; 1313 std::vector<uint8_t> vec = {'"', '\\', '"', 'X', '"', '"'}; 1314 CHECK_THROWS_AS(_ = json::parse(vec), json::parse_error&); 1315 } 1316 1317 #if JSON_USE_IMPLICIT_CONVERSIONS 1318 SECTION("issue #600 - how does one convert a map in Json back to std::map?") 1319 { 1320 SECTION("example 1") 1321 { 1322 // create a map 1323 std::map<std::string, int> m1 {{"key", 1}}; 1324 1325 // create and print a JSON from the map 1326 json j = m1; 1327 1328 // get the map out of JSON 1329 std::map<std::string, int> m2 = j; 1330 1331 // make sure the roundtrip succeeds 1332 CHECK(m1 == m2); 1333 } 1334 1335 SECTION("example 2") 1336 { 1337 // create a map 1338 std::map<std::string, std::string> m1 {{"key", "val"}}; 1339 1340 // create and print a JSON from the map 1341 json j = m1; 1342 1343 // get the map out of JSON 1344 std::map<std::string, std::string> m2 = j; 1345 1346 // make sure the roundtrip succeeds 1347 CHECK(m1 == m2); 1348 } 1349 } 1350 #endif 1351 1352 SECTION("issue #602 - BOM not skipped when using json:parse(iterator)") 1353 { 1354 std::string i = "\xef\xbb\xbf{\n \"foo\": true\n}"; 1355 json _; 1356 CHECK_NOTHROW(_ = json::parse(i.begin(), i.end())); 1357 } 1358 1359 #if JSON_USE_IMPLICIT_CONVERSIONS 1360 SECTION("issue #702 - conversion from valarray<double> to json fails to build") 1361 { 1362 SECTION("original example") 1363 { 1364 std::valarray<double> v; 1365 nlohmann::json j; 1366 j["test"] = v; 1367 } 1368 1369 SECTION("full example") 1370 { 1371 std::valarray<double> v = {1.2, 2.3, 3.4, 4.5}; 1372 json j = v; 1373 std::valarray<double> vj = j; 1374 1375 CHECK(j == json(vj)); 1376 CHECK(v.size() == vj.size()); 1377 for (size_t i = 0; i < v.size(); ++i) 1378 { 1379 CHECK(v[i] == vj[i]); 1380 CHECK(v[i] == j[i]); 1381 } 1382 1383 CHECK_THROWS_AS(json().get<std::valarray<double>>(), json::type_error&); 1384 CHECK_THROWS_WITH(json().get<std::valarray<double>>(), 1385 "[json.exception.type_error.302] type must be array, but is null"); 1386 } 1387 } 1388 #endif 1389 1390 SECTION("issue #367 - Behavior of operator>> should more closely resemble that of built-in overloads.") 1391 { 1392 SECTION("example 1") 1393 { 1394 std::istringstream i1_2_3( R"({"first": "one" }{"second": "two"}3)" ); 1395 json j1; 1396 json j2; 1397 json j3; 1398 i1_2_3 >> j1; 1399 i1_2_3 >> j2; 1400 i1_2_3 >> j3; 1401 1402 auto m1 = j1.get<std::map<std::string, std::string>>(); 1403 auto m2 = j2.get<std::map<std::string, std::string>>(); 1404 int i3{j3}; 1405 1406 CHECK( m1 == ( std::map<std::string, std::string> {{ "first", "one" }} )); 1407 CHECK( m2 == ( std::map<std::string, std::string> {{ "second", "two" }} )); 1408 CHECK( i3 == 3 ); 1409 } 1410 } 1411 1412 SECTION("issue #714 - throw std::ios_base::failure exception when failbit set to true") 1413 { 1414 { 1415 std::ifstream is; 1416 is.exceptions( 1417 is.exceptions() 1418 | std::ios_base::failbit 1419 | std::ios_base::badbit 1420 ); // handle different exceptions as 'file not found', 'permission denied' 1421 1422 is.open(TEST_DATA_DIRECTORY "/regression/working_file.json"); 1423 json _; 1424 CHECK_NOTHROW(_ = nlohmann::json::parse(is)); 1425 } 1426 1427 { 1428 std::ifstream is; 1429 is.exceptions( 1430 is.exceptions() 1431 | std::ios_base::failbit 1432 | std::ios_base::badbit 1433 ); // handle different exceptions as 'file not found', 'permission denied' 1434 1435 is.open(TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json.cbor", 1436 std::ios_base::in | std::ios_base::binary); 1437 json _; 1438 CHECK_NOTHROW(_ = nlohmann::json::from_cbor(is)); 1439 } 1440 } 1441 1442 SECTION("issue #805 - copy constructor is used with std::initializer_list constructor.") 1443 { 1444 nocopy n; 1445 json j; 1446 j = {{"nocopy", n}}; 1447 CHECK(j["nocopy"]["val"] == 0); 1448 } 1449 1450 SECTION("issue #838 - incorrect parse error with binary data in keys") 1451 { 1452 std::array<uint8_t, 28> key1 = {{ 103, 92, 117, 48, 48, 48, 55, 92, 114, 215, 126, 214, 95, 92, 34, 174, 40, 71, 38, 174, 40, 71, 38, 223, 134, 247, 127, 0 }}; 1453 std::string key1_str(reinterpret_cast<char*>(key1.data())); 1454 json j = key1_str; 1455 CHECK_THROWS_AS(j.dump(), json::type_error&); 1456 CHECK_THROWS_WITH(j.dump(), "[json.exception.type_error.316] invalid UTF-8 byte at index 10: 0x7E"); 1457 } 1458 1459 #if JSON_USE_IMPLICIT_CONVERSIONS 1460 SECTION("issue #843 - converting to array not working") 1461 { 1462 json j; 1463 std::array<int, 4> ar = {{1, 1, 1, 1}}; 1464 j = ar; 1465 ar = j; 1466 } 1467 #endif 1468 1469 SECTION("issue #894 - invalid RFC6902 copy operation succeeds") 1470 { 1471 auto model = R"({ 1472 "one": { 1473 "two": { 1474 "three": "hello", 1475 "four": 42 1476 } 1477 } 1478 })"_json; 1479 1480 auto p1 = R"([{"op": "move", 1481 "from": "/one/two/three", 1482 "path": "/a/b/c"}])"_json; 1483 CHECK_THROWS_AS(model.patch(p1), json::out_of_range&); 1484 1485 auto p2 = R"([{"op": "move", 1486 "from": "/one/two/three", 1487 "path": "/a/b/c"}])"_json; 1488 CHECK_THROWS_WITH(model.patch(p2), 1489 "[json.exception.out_of_range.403] key 'a' not found"); 1490 1491 auto p3 = R"([{"op": "copy", 1492 "from": "/one/two/three", 1493 "path": "/a/b/c"}])"_json; 1494 CHECK_THROWS_AS(model.patch(p3), json::out_of_range&); 1495 1496 auto p4 = R"([{"op": "copy", 1497 "from": "/one/two/three", 1498 "path": "/a/b/c"}])"_json; 1499 CHECK_THROWS_WITH(model.patch(p4), 1500 "[json.exception.out_of_range.403] key 'a' not found"); 1501 } 1502 1503 SECTION("issue #961 - incorrect parsing of indefinite length CBOR strings") 1504 { 1505 std::vector<uint8_t> v_cbor = 1506 { 1507 0x7F, 1508 0x64, 1509 'a', 'b', 'c', 'd', 1510 0x63, 1511 '1', '2', '3', 1512 0xFF 1513 }; 1514 json j = json::from_cbor(v_cbor); 1515 CHECK(j == "abcd123"); 1516 } 1517 1518 SECTION("issue #962 - Timeout (OSS-Fuzz 6034)") 1519 { 1520 json _; 1521 std::vector<uint8_t> v_ubjson = {'[', '$', 'Z', '#', 'L', 0x78, 0x28, 0x00, 0x68, 0x28, 0x69, 0x69, 0x17}; 1522 CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&); 1523 //CHECK_THROWS_WITH(json::from_ubjson(v_ubjson), 1524 // "[json.exception.out_of_range.408] excessive array size: 8658170730974374167"); 1525 1526 v_ubjson[0] = '{'; 1527 CHECK_THROWS_AS(_ = json::from_ubjson(v_ubjson), json::out_of_range&); 1528 //CHECK_THROWS_WITH(json::from_ubjson(v_ubjson), 1529 // "[json.exception.out_of_range.408] excessive object size: 8658170730974374167"); 1530 } 1531 1532 SECTION("issue #971 - Add a SAX parser - late bug") 1533 { 1534 // a JSON text 1535 const auto* text = R"( 1536 { 1537 "Image": { 1538 "Width": 800, 1539 "Height": 600, 1540 "Title": "View from 15th Floor", 1541 "Thumbnail": { 1542 "Url": "http://www.example.com/image/481989943", 1543 "Height": 125, 1544 "Width": 100 1545 }, 1546 "Animated" : false, 1547 "IDs": [116, 943, 234, 38793] 1548 } 1549 } 1550 )"; 1551 1552 // define parser callback 1553 json::parser_callback_t cb = [](int /*depth*/, json::parse_event_t event, json & parsed) __anon1124f2ca0902(int , json::parse_event_t event, json & parsed) 1554 { 1555 // skip object elements with key "Thumbnail" 1556 return !(event == json::parse_event_t::key && parsed == json("Thumbnail")); 1557 }; 1558 1559 // parse (with callback) and serialize JSON 1560 json j_filtered = json::parse(text, cb); 1561 1562 CHECK(j_filtered == R"({"Image":{"Animated":false,"Height":600,"IDs":[116,943,234,38793], "Title":"View from 15th Floor","Width":800}})"_json); 1563 } 1564 1565 SECTION("issue #972 - Segmentation fault on G++ when trying to assign json string literal to custom json type") 1566 { 1567 my_json foo = R"([1, 2, 3])"_json; 1568 } 1569 1570 SECTION("issue #977 - Assigning between different json types") 1571 { 1572 foo_json lj = ns::foo{3}; 1573 ns::foo ff(lj); 1574 CHECK(lj.is_object()); 1575 CHECK(lj.size() == 1); 1576 CHECK(lj["x"] == 3); 1577 CHECK(ff.x == 3); 1578 nlohmann::json nj = lj; // This line works as expected 1579 } 1580 } 1581 1582 #if !defined(JSON_NOEXCEPTION) 1583 TEST_CASE("regression tests, exceptions dependent") 1584 { 1585 SECTION("issue #1340 - eof not set on exhausted input stream") 1586 { 1587 std::stringstream s("{}{}"); 1588 json j; 1589 s >> j; 1590 s >> j; 1591 CHECK_THROWS_AS(s >> j, json::parse_error const&); 1592 CHECK(s.eof()); 1593 } 1594 } 1595 #endif 1596 1597 ///////////////////////////////////////////////////////////////////// 1598 // for #1642 1599 ///////////////////////////////////////////////////////////////////// 1600 1601 // the code below fails with Clang on Windows, so we need to exclude it there 1602 #if defined(__clang__) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)) 1603 #else 1604 template <typename T> class array {}; 1605 template <typename T> class object {}; 1606 template <typename T> class string {}; 1607 template <typename T> class number_integer {}; 1608 template <typename T> class number_unsigned {}; 1609 template <typename T> class number_float {}; 1610 #endif 1611