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