Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
40b78d38
Unverified
Commit
40b78d38
authored
4 years ago
by
Niels Lohmann
Committed by
GitHub
4 years ago
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2308 from nlohmann/cbor_tags
Fix bug in CBOR tag handling
parents
a1dbfcd7
480ad529
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
73 additions
and
44 deletions
+73
-44
include/nlohmann/detail/input/binary_reader.hpp
include/nlohmann/detail/input/binary_reader.hpp
+26
-22
single_include/nlohmann/json.hpp
single_include/nlohmann/json.hpp
+26
-22
test/src/unit-cbor.cpp
test/src/unit-cbor.cpp
+21
-0
No files found.
include/nlohmann/detail/input/binary_reader.hpp
View file @
40b78d38
...
@@ -393,14 +393,14 @@ class binary_reader
...
@@ -393,14 +393,14 @@ class binary_reader
/*!
/*!
@param[in] get_char whether a new character should be retrieved from the
@param[in] get_char whether a new character should be retrieved from the
input (true
, default) or whether the last rea
d
input (true
) or whether the last read character shoul
d
character should be considered instead
be considered instead (false)
@param[in] tag_handler how CBOR tags should be treated
@param[in] tag_handler how CBOR tags should be treated
@return whether a valid CBOR value was passed to the SAX parser
@return whether a valid CBOR value was passed to the SAX parser
*/
*/
bool
parse_cbor_internal
(
const
bool
get_char
=
true
,
bool
parse_cbor_internal
(
const
bool
get_char
,
c
bor_tag_handler_t
tag_handler
=
cbor_tag_handler_t
::
erro
r
)
c
onst
cbor_tag_handler_t
tag_handle
r
)
{
{
switch
(
get_char
?
get
()
:
current
)
switch
(
get_char
?
get
()
:
current
)
{
{
...
@@ -606,34 +606,34 @@ class binary_reader
...
@@ -606,34 +606,34 @@ class binary_reader
case
0x95
:
case
0x95
:
case
0x96
:
case
0x96
:
case
0x97
:
case
0x97
:
return
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
static_cast
<
unsigned
int
>
(
current
)
&
0x1Fu
));
return
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
static_cast
<
unsigned
int
>
(
current
)
&
0x1Fu
)
,
tag_handler
);
case
0x98
:
// array (one-byte uint8_t for n follows)
case
0x98
:
// array (one-byte uint8_t for n follows)
{
{
std
::
uint8_t
len
{};
std
::
uint8_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0x99
:
// array (two-byte uint16_t for n follow)
case
0x99
:
// array (two-byte uint16_t for n follow)
{
{
std
::
uint16_t
len
{};
std
::
uint16_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0x9A
:
// array (four-byte uint32_t for n follow)
case
0x9A
:
// array (four-byte uint32_t for n follow)
{
{
std
::
uint32_t
len
{};
std
::
uint32_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0x9B
:
// array (eight-byte uint64_t for n follow)
case
0x9B
:
// array (eight-byte uint64_t for n follow)
{
{
std
::
uint64_t
len
{};
std
::
uint64_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_array
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0x9F
:
// array (indefinite length)
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)
// map (0x00..0x17 pairs of data items follow)
case
0xA0
:
case
0xA0
:
...
@@ -660,34 +660,34 @@ class binary_reader
...
@@ -660,34 +660,34 @@ class binary_reader
case
0xB5
:
case
0xB5
:
case
0xB6
:
case
0xB6
:
case
0xB7
:
case
0xB7
:
return
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
static_cast
<
unsigned
int
>
(
current
)
&
0x1Fu
));
return
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
static_cast
<
unsigned
int
>
(
current
)
&
0x1Fu
)
,
tag_handler
);
case
0xB8
:
// map (one-byte uint8_t for n follows)
case
0xB8
:
// map (one-byte uint8_t for n follows)
{
{
std
::
uint8_t
len
{};
std
::
uint8_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0xB9
:
// map (two-byte uint16_t for n follow)
case
0xB9
:
// map (two-byte uint16_t for n follow)
{
{
std
::
uint16_t
len
{};
std
::
uint16_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0xBA
:
// map (four-byte uint32_t for n follow)
case
0xBA
:
// map (four-byte uint32_t for n follow)
{
{
std
::
uint32_t
len
{};
std
::
uint32_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0xBB
:
// map (eight-byte uint64_t for n follow)
case
0xBB
:
// map (eight-byte uint64_t for n follow)
{
{
std
::
uint64_t
len
{};
std
::
uint64_t
len
{};
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
));
return
get_number
(
input_format_t
::
cbor
,
len
)
&&
get_cbor_object
(
static_cast
<
std
::
size_t
>
(
len
)
,
tag_handler
);
}
}
case
0xBF
:
// map (indefinite length)
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
0xC6
:
// tagged item
case
0xC7
:
case
0xC7
:
...
@@ -1030,9 +1030,11 @@ class binary_reader
...
@@ -1030,9 +1030,11 @@ class binary_reader
/*!
/*!
@param[in] len the length of the array or std::size_t(-1) for an
@param[in] len the length of the array or std::size_t(-1) for an
array of indefinite size
array of indefinite size
@param[in] tag_handler how CBOR tags should be treated
@return whether array creation completed
@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
)))
if
(
JSON_HEDLEY_UNLIKELY
(
!
sax
->
start_array
(
len
)))
{
{
...
@@ -1043,7 +1045,7 @@ class binary_reader
...
@@ -1043,7 +1045,7 @@ class binary_reader
{
{
for
(
std
::
size_t
i
=
0
;
i
<
len
;
++
i
)
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
;
return
false
;
}
}
...
@@ -1053,7 +1055,7 @@ class binary_reader
...
@@ -1053,7 +1055,7 @@ class binary_reader
{
{
while
(
get
()
!=
0xFF
)
while
(
get
()
!=
0xFF
)
{
{
if
(
JSON_HEDLEY_UNLIKELY
(
!
parse_cbor_internal
(
false
)))
if
(
JSON_HEDLEY_UNLIKELY
(
!
parse_cbor_internal
(
false
,
tag_handler
)))
{
{
return
false
;
return
false
;
}
}
...
@@ -1066,9 +1068,11 @@ class binary_reader
...
@@ -1066,9 +1068,11 @@ class binary_reader
/*!
/*!
@param[in] len the length of the object or std::size_t(-1) for an
@param[in] len the length of the object or std::size_t(-1) for an
object of indefinite size
object of indefinite size
@param[in] tag_handler how CBOR tags should be treated
@return whether object creation completed
@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
)))
if
(
JSON_HEDLEY_UNLIKELY
(
!
sax
->
start_object
(
len
)))
{
{
...
@@ -1086,7 +1090,7 @@ class binary_reader
...
@@ -1086,7 +1090,7 @@ class binary_reader
return
false
;
return
false
;
}
}
if
(
JSON_HEDLEY_UNLIKELY
(
!
parse_cbor_internal
()))
if
(
JSON_HEDLEY_UNLIKELY
(
!
parse_cbor_internal
(
true
,
tag_handler
)))
{
{
return
false
;
return
false
;
}
}
...
@@ -1102,7 +1106,7 @@ class binary_reader
...
@@ -1102,7 +1106,7 @@ class binary_reader
return
false
;
return
false
;
}
}
if
(
JSON_HEDLEY_UNLIKELY
(
!
parse_cbor_internal
()))
if
(
JSON_HEDLEY_UNLIKELY
(
!
parse_cbor_internal
(
true
,
tag_handler
)))
{
{
return
false
;
return
false
;
}
}
...
...
This diff is collapsed.
Click to expand it.
single_include/nlohmann/json.hpp
View file @
40b78d38
...
@@ -6402,14 +6402,14 @@ class binary_reader
...
@@ -6402,14 +6402,14 @@ class binary_reader
/*!
/*!
@param[in] get_char whether a new character should be retrieved from the
@param[in] get_char whether a new character should be retrieved from the
input (true
, default) or whether the last rea
d
input (true
) or whether the last read character shoul
d
character should be considered instead
be considered instead (false)
@param[in] tag_handler how CBOR tags should be treated
@param[in] tag_handler how CBOR tags should be treated
@return whether a valid CBOR value was passed to the SAX parser
@return whether a valid CBOR value was passed to the SAX parser
*/
*/
bool parse_cbor_internal(const bool get_char
= true
,
bool parse_cbor_internal(const bool get_char,
c
bor_tag_handler_t tag_handler = cbor_tag_handler_t::erro
r)
c
onst cbor_tag_handler_t tag_handle
r)
{
{
switch (get_char ? get() : current)
switch (get_char ? get() : current)
{
{
...
@@ -6615,34 +6615,34 @@ class binary_reader
...
@@ -6615,34 +6615,34 @@ class binary_reader
case 0x95:
case 0x95:
case 0x96:
case 0x96:
case 0x97:
case 0x97:
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu)
, tag_handler
);
case 0x98: // array (one-byte uint8_t for n follows)
case 0x98: // array (one-byte uint8_t for n follows)
{
{
std::uint8_t len{};
std::uint8_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0x99: // array (two-byte uint16_t for n follow)
case 0x99: // array (two-byte uint16_t for n follow)
{
{
std::uint16_t len{};
std::uint16_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0x9A: // array (four-byte uint32_t for n follow)
case 0x9A: // array (four-byte uint32_t for n follow)
{
{
std::uint32_t len{};
std::uint32_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0x9B: // array (eight-byte uint64_t for n follow)
case 0x9B: // array (eight-byte uint64_t for n follow)
{
{
std::uint64_t len{};
std::uint64_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0x9F: // array (indefinite length)
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)
// map (0x00..0x17 pairs of data items follow)
case 0xA0:
case 0xA0:
...
@@ -6669,34 +6669,34 @@ class binary_reader
...
@@ -6669,34 +6669,34 @@ class binary_reader
case 0xB5:
case 0xB5:
case 0xB6:
case 0xB6:
case 0xB7:
case 0xB7:
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu)
, tag_handler
);
case 0xB8: // map (one-byte uint8_t for n follows)
case 0xB8: // map (one-byte uint8_t for n follows)
{
{
std::uint8_t len{};
std::uint8_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0xB9: // map (two-byte uint16_t for n follow)
case 0xB9: // map (two-byte uint16_t for n follow)
{
{
std::uint16_t len{};
std::uint16_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0xBA: // map (four-byte uint32_t for n follow)
case 0xBA: // map (four-byte uint32_t for n follow)
{
{
std::uint32_t len{};
std::uint32_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0xBB: // map (eight-byte uint64_t for n follow)
case 0xBB: // map (eight-byte uint64_t for n follow)
{
{
std::uint64_t len{};
std::uint64_t len{};
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len));
return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len)
, tag_handler
);
}
}
case 0xBF: // map (indefinite length)
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 0xC6: // tagged item
case 0xC7:
case 0xC7:
...
@@ -7039,9 +7039,11 @@ class binary_reader
...
@@ -7039,9 +7039,11 @@ class binary_reader
/*!
/*!
@param[in] len the length of the array or std::size_t(-1) for an
@param[in] len the length of the array or std::size_t(-1) for an
array of indefinite size
array of indefinite size
@param[in] tag_handler how CBOR tags should be treated
@return whether array creation completed
@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)))
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
{
{
...
@@ -7052,7 +7054,7 @@ class binary_reader
...
@@ -7052,7 +7054,7 @@ class binary_reader
{
{
for (std::size_t i = 0; i < len; ++i)
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;
return false;
}
}
...
@@ -7062,7 +7064,7 @@ class binary_reader
...
@@ -7062,7 +7064,7 @@ class binary_reader
{
{
while (get() != 0xFF)
while (get() != 0xFF)
{
{
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false)))
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false
, tag_handler
)))
{
{
return false;
return false;
}
}
...
@@ -7075,9 +7077,11 @@ class binary_reader
...
@@ -7075,9 +7077,11 @@ class binary_reader
/*!
/*!
@param[in] len the length of the object or std::size_t(-1) for an
@param[in] len the length of the object or std::size_t(-1) for an
object of indefinite size
object of indefinite size
@param[in] tag_handler how CBOR tags should be treated
@return whether object creation completed
@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)))
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
{
{
...
@@ -7095,7 +7099,7 @@ class binary_reader
...
@@ -7095,7 +7099,7 @@ class binary_reader
return false;
return false;
}
}
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler
)))
{
{
return false;
return false;
}
}
...
@@ -7111,7 +7115,7 @@ class binary_reader
...
@@ -7111,7 +7115,7 @@ class binary_reader
return false;
return false;
}
}
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal()))
if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler
)))
{
{
return false;
return false;
}
}
...
...
This diff is collapsed.
Click to expand it.
test/src/unit-cbor.cpp
View file @
40b78d38
...
@@ -2705,4 +2705,25 @@ TEST_CASE("Tagged values")
...
@@ -2705,4 +2705,25 @@ TEST_CASE("Tagged values")
CHECK_THROWS_AS
(
json
::
from_cbor
(
v_tagged
,
true
,
true
,
json
::
cbor_tag_handler_t
::
ignore
),
json
::
parse_error
);
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
<
std
::
uint8_t
>
{
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
());
}
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment