]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentelemetry-cpp/third_party/nlohmann-json/test/src/unit-regression1.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / jaegertracing / opentelemetry-cpp / third_party / nlohmann-json / test / src / unit-regression1.cpp
1 /*
2 __ _____ _____ _____
3 __| | __| | | | JSON for Modern C++ (test suite)
4 | | |__ | | | | | | version 3.10.5
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-2022 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>
81 static void to_json(BasicJsonType& j, const T& value)
82 {
83 j = BasicJsonType{{"x", value.x}};
84 }
85 template <typename BasicJsonType>
86 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>
96 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>
101 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
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 = static_cast<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 = static_cast<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, "types must be the same");
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)
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)
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:
523 char do_decimal_point() const override
524 {
525 return ',';
526 }
527
528 char do_thousands_sep() const override
529 {
530 return '.';
531 }
532
533 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 static_cast<void>(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 static_cast<void>(setlocale(LC_NUMERIC, "C"));
576 }
577
578 SECTION("issue #379 - locale-independent str-to-num")
579 {
580 static_cast<void>(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)
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 static_cast<void>(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)
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)
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)
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)
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