diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 72e652a4..edd4c4f7 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -393,14 +393,14 @@ class binary_reader /*! @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead + input (true) or whether the last read character should + be considered instead (false) @param[in] tag_handler how CBOR tags should be treated @return whether a valid CBOR value was passed to the SAX parser */ - bool parse_cbor_internal(const bool get_char = true, - cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + bool parse_cbor_internal(const bool get_char, + const cbor_tag_handler_t tag_handler) { switch (get_char ? get() : current) { @@ -606,34 +606,34 @@ class binary_reader case 0x95: case 0x96: case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu)); + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0x98: // array (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x99: // array (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x9A: // array (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x9B: // array (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x9F: // array (indefinite length) - return get_cbor_array(std::size_t(-1)); + return get_cbor_array(std::size_t(-1), tag_handler); // map (0x00..0x17 pairs of data items follow) case 0xA0: @@ -660,34 +660,34 @@ class binary_reader case 0xB5: case 0xB6: case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu)); + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0xB8: // map (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xB9: // map (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xBA: // map (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xBB: // map (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xBF: // map (indefinite length) - return get_cbor_object(std::size_t(-1)); + return get_cbor_object(std::size_t(-1), tag_handler); case 0xC6: // tagged item case 0xC7: @@ -1030,9 +1030,11 @@ class binary_reader /*! @param[in] len the length of the array or std::size_t(-1) for an array of indefinite size + @param[in] tag_handler how CBOR tags should be treated @return whether array creation completed */ - bool get_cbor_array(const std::size_t len) + bool get_cbor_array(const std::size_t len, + const cbor_tag_handler_t tag_handler) { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) { @@ -1043,7 +1045,7 @@ class binary_reader { for (std::size_t i = 0; i < len; ++i) { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal())) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } @@ -1053,7 +1055,7 @@ class binary_reader { while (get() != 0xFF) { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false))) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) { return false; } @@ -1066,9 +1068,11 @@ class binary_reader /*! @param[in] len the length of the object or std::size_t(-1) for an object of indefinite size + @param[in] tag_handler how CBOR tags should be treated @return whether object creation completed */ - bool get_cbor_object(const std::size_t len) + bool get_cbor_object(const std::size_t len, + const cbor_tag_handler_t tag_handler) { if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) { @@ -1086,7 +1090,7 @@ class binary_reader return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal())) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } @@ -1102,7 +1106,7 @@ class binary_reader return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal())) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0b7d2411..069bfc57 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -6402,14 +6402,14 @@ class binary_reader /*! @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead + input (true) or whether the last read character should + be considered instead (false) @param[in] tag_handler how CBOR tags should be treated @return whether a valid CBOR value was passed to the SAX parser */ - bool parse_cbor_internal(const bool get_char = true, - cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) + bool parse_cbor_internal(const bool get_char, + const cbor_tag_handler_t tag_handler) { switch (get_char ? get() : current) { @@ -6615,34 +6615,34 @@ class binary_reader case 0x95: case 0x96: case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu)); + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0x98: // array (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x99: // array (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x9A: // array (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x9B: // array (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); } case 0x9F: // array (indefinite length) - return get_cbor_array(std::size_t(-1)); + return get_cbor_array(std::size_t(-1), tag_handler); // map (0x00..0x17 pairs of data items follow) case 0xA0: @@ -6669,34 +6669,34 @@ class binary_reader case 0xB5: case 0xB6: case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu)); + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); case 0xB8: // map (one-byte uint8_t for n follows) { std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xB9: // map (two-byte uint16_t for n follow) { std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xBA: // map (four-byte uint32_t for n follow) { std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xBB: // map (eight-byte uint64_t for n follow) { std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len)); + return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); } case 0xBF: // map (indefinite length) - return get_cbor_object(std::size_t(-1)); + return get_cbor_object(std::size_t(-1), tag_handler); case 0xC6: // tagged item case 0xC7: @@ -7039,9 +7039,11 @@ class binary_reader /*! @param[in] len the length of the array or std::size_t(-1) for an array of indefinite size + @param[in] tag_handler how CBOR tags should be treated @return whether array creation completed */ - bool get_cbor_array(const std::size_t len) + bool get_cbor_array(const std::size_t len, + const cbor_tag_handler_t tag_handler) { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) { @@ -7052,7 +7054,7 @@ class binary_reader { for (std::size_t i = 0; i < len; ++i) { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal())) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } @@ -7062,7 +7064,7 @@ class binary_reader { while (get() != 0xFF) { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false))) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) { return false; } @@ -7075,9 +7077,11 @@ class binary_reader /*! @param[in] len the length of the object or std::size_t(-1) for an object of indefinite size + @param[in] tag_handler how CBOR tags should be treated @return whether object creation completed */ - bool get_cbor_object(const std::size_t len) + bool get_cbor_object(const std::size_t len, + const cbor_tag_handler_t tag_handler) { if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) { @@ -7095,7 +7099,7 @@ class binary_reader return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal())) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } @@ -7111,7 +7115,7 @@ class binary_reader return false; } - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal())) + if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) { return false; } diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 7eaba84a..96613fb5 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -2722,4 +2722,25 @@ TEST_CASE("Tagged values") CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error); } } + + SECTION("tagged binary") + { + // create a binary value of subtype 42 + json j; + j["binary"] = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 42); + + // convert to CBOR + const auto v = json::to_cbor(j); + CHECK(v == std::vector {0xA1, 0x66, 0x62, 0x69, 0x6E, 0x61, 0x72, 0x79, 0xD8, 0x2A, 0x44, 0xCA, 0xFE, 0xBA, 0xBE}); + + // parse error when parsing tagged value + CHECK_THROWS_AS(json::from_cbor(v), json::parse_error); + CHECK_THROWS_WITH(json::from_cbor(v), "[json.exception.parse_error.112] parse error at byte 9: syntax error while parsing CBOR value: invalid byte: 0xD8"); + + // binary without subtype when tags are ignored + json jb = json::from_cbor(v, true, true, json::cbor_tag_handler_t::ignore); + CHECK(jb.is_object()); + CHECK(jb["binary"].is_binary()); + CHECK(!jb["binary"].get_binary().has_subtype()); + } }