Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
4bfe4add
Unverified
Commit
4bfe4add
authored
Jun 23, 2020
by
Niels Lohmann
Committed by
GitHub
Jun 23, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2203 from t-b/use-unsigned-indizies-for-array-index-in-json-pointer
Use unsigned indizies for array index in json pointer
parents
29ad2178
ecbb2756
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
73 additions
and
34 deletions
+73
-34
json_pointer.hpp
include/nlohmann/detail/json_pointer.hpp
+23
-12
json.hpp
include/nlohmann/json.hpp
+2
-2
json.hpp
single_include/nlohmann/json.hpp
+25
-14
unit-json_pointer.cpp
test/src/unit-json_pointer.cpp
+23
-6
No files found.
include/nlohmann/detail/json_pointer.hpp
View file @
4bfe4add
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
#include <algorithm> // all_of
#include <algorithm> // all_of
#include <cassert> // assert
#include <cassert> // assert
#include <cctype> // isdigit
#include <cctype> // isdigit
#include <limits> // max
#include <numeric> // accumulate
#include <numeric> // accumulate
#include <string> // string
#include <string> // string
#include <utility> // move
#include <utility> // move
...
@@ -325,10 +326,15 @@ class json_pointer
...
@@ -325,10 +326,15 @@ class json_pointer
@return integer representation of @a s
@return integer representation of @a s
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index begins not with a digit
@throw out_of_range.404 if string @a s could not be converted to an integer
@throw out_of_range.404 if string @a s could not be converted to an integer
@throw out_of_range.410 if an array index exceeds size_type
*/
*/
static
int
array_index
(
const
std
::
string
&
s
)
static
typename
BasicJsonType
::
size_type
array_index
(
const
std
::
string
&
s
)
{
{
using
size_type
=
typename
BasicJsonType
::
size_type
;
// error condition (cf. RFC 6901, Sect. 4)
// error condition (cf. RFC 6901, Sect. 4)
if
(
JSON_HEDLEY_UNLIKELY
(
s
.
size
()
>
1
and
s
[
0
]
==
'0'
))
if
(
JSON_HEDLEY_UNLIKELY
(
s
.
size
()
>
1
and
s
[
0
]
==
'0'
))
{
{
...
@@ -344,10 +350,10 @@ class json_pointer
...
@@ -344,10 +350,10 @@ class json_pointer
}
}
std
::
size_t
processed_chars
=
0
;
std
::
size_t
processed_chars
=
0
;
int
res
=
0
;
unsigned
long
long
res
=
0
;
JSON_TRY
JSON_TRY
{
{
res
=
std
::
sto
i
(
s
,
&
processed_chars
);
res
=
std
::
sto
ull
(
s
,
&
processed_chars
);
}
}
JSON_CATCH
(
std
::
out_of_range
&
)
JSON_CATCH
(
std
::
out_of_range
&
)
{
{
...
@@ -360,7 +366,14 @@ class json_pointer
...
@@ -360,7 +366,14 @@ class json_pointer
JSON_THROW
(
detail
::
out_of_range
::
create
(
404
,
"unresolved reference token '"
+
s
+
"'"
));
JSON_THROW
(
detail
::
out_of_range
::
create
(
404
,
"unresolved reference token '"
+
s
+
"'"
));
}
}
return
res
;
// only triggered on special platforms (like 32bit), see also
// https://github.com/nlohmann/json/pull/2203
if
(
res
>=
static_cast
<
unsigned
long
long
>
((
std
::
numeric_limits
<
size_type
>::
max
)()))
{
JSON_THROW
(
detail
::
out_of_range
::
create
(
410
,
"array index "
+
s
+
" exceeds size_type"
));
// LCOV_EXCL_LINE
}
return
static_cast
<
size_type
>
(
res
);
}
}
json_pointer
top
()
const
json_pointer
top
()
const
...
@@ -419,7 +432,7 @@ class json_pointer
...
@@ -419,7 +432,7 @@ class json_pointer
case
detail
:
:
value_t
::
array
:
case
detail
:
:
value_t
::
array
:
{
{
// create an entry in the array
// create an entry in the array
result
=
&
result
->
operator
[](
static_cast
<
size_type
>
(
array_index
(
reference_token
)
));
result
=
&
result
->
operator
[](
array_index
(
reference_token
));
break
;
break
;
}
}
...
@@ -497,8 +510,7 @@ class json_pointer
...
@@ -497,8 +510,7 @@ class json_pointer
else
else
{
{
// convert array index to number; unchecked access
// convert array index to number; unchecked access
ptr
=
&
ptr
->
operator
[](
ptr
=
&
ptr
->
operator
[](
array_index
(
reference_token
));
static_cast
<
size_type
>
(
array_index
(
reference_token
)));
}
}
break
;
break
;
}
}
...
@@ -542,7 +554,7 @@ class json_pointer
...
@@ -542,7 +554,7 @@ class json_pointer
}
}
// note: at performs range check
// note: at performs range check
ptr
=
&
ptr
->
at
(
static_cast
<
size_type
>
(
array_index
(
reference_token
)
));
ptr
=
&
ptr
->
at
(
array_index
(
reference_token
));
break
;
break
;
}
}
...
@@ -592,8 +604,7 @@ class json_pointer
...
@@ -592,8 +604,7 @@ class json_pointer
}
}
// use unchecked array access
// use unchecked array access
ptr
=
&
ptr
->
operator
[](
ptr
=
&
ptr
->
operator
[](
array_index
(
reference_token
));
static_cast
<
size_type
>
(
array_index
(
reference_token
)));
break
;
break
;
}
}
...
@@ -636,7 +647,7 @@ class json_pointer
...
@@ -636,7 +647,7 @@ class json_pointer
}
}
// note: at performs range check
// note: at performs range check
ptr
=
&
ptr
->
at
(
static_cast
<
size_type
>
(
array_index
(
reference_token
)
));
ptr
=
&
ptr
->
at
(
array_index
(
reference_token
));
break
;
break
;
}
}
...
@@ -700,7 +711,7 @@ class json_pointer
...
@@ -700,7 +711,7 @@ class json_pointer
}
}
}
}
const
auto
idx
=
static_cast
<
size_type
>
(
array_index
(
reference_token
)
);
const
auto
idx
=
array_index
(
reference_token
);
if
(
idx
>=
ptr
->
size
())
if
(
idx
>=
ptr
->
size
())
{
{
// index out of range
// index out of range
...
...
include/nlohmann/json.hpp
View file @
4bfe4add
...
@@ -8207,7 +8207,7 @@ class basic_json
...
@@ -8207,7 +8207,7 @@ class basic_json
else
else
{
{
const
auto
idx
=
json_pointer
::
array_index
(
last_path
);
const
auto
idx
=
json_pointer
::
array_index
(
last_path
);
if
(
JSON_HEDLEY_UNLIKELY
(
static_cast
<
size_type
>
(
idx
)
>
parent
.
size
()))
if
(
JSON_HEDLEY_UNLIKELY
(
idx
>
parent
.
size
()))
{
{
// avoid undefined behavior
// avoid undefined behavior
JSON_THROW
(
out_of_range
::
create
(
401
,
"array index "
+
std
::
to_string
(
idx
)
+
" is out of range"
));
JSON_THROW
(
out_of_range
::
create
(
401
,
"array index "
+
std
::
to_string
(
idx
)
+
" is out of range"
));
...
@@ -8250,7 +8250,7 @@ class basic_json
...
@@ -8250,7 +8250,7 @@ class basic_json
else
if
(
parent
.
is_array
())
else
if
(
parent
.
is_array
())
{
{
// note erase performs range check
// note erase performs range check
parent
.
erase
(
static_cast
<
size_type
>
(
json_pointer
::
array_index
(
last_path
)
));
parent
.
erase
(
json_pointer
::
array_index
(
last_path
));
}
}
};
};
...
...
single_include/nlohmann/json.hpp
View file @
4bfe4add
...
@@ -11036,6 +11036,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
...
@@ -11036,6 +11036,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
#include <algorithm> // all_of
#include <algorithm> // all_of
#include <cassert> // assert
#include <cassert> // assert
#include <cctype> // isdigit
#include <cctype> // isdigit
#include <limits> // max
#include <numeric> // accumulate
#include <numeric> // accumulate
#include <string> // string
#include <string> // string
#include <utility> // move
#include <utility> // move
...
@@ -11361,10 +11362,15 @@ class json_pointer
...
@@ -11361,10 +11362,15 @@ class json_pointer
@return integer representation of @a s
@return integer representation of @a s
@throw parse_error.106 if an array index begins with '0'
@throw parse_error.109 if an array index begins not with a digit
@throw out_of_range.404 if string @a s could not be converted to an integer
@throw out_of_range.404 if string @a s could not be converted to an integer
@throw out_of_range.410 if an array index exceeds size_type
*/
*/
static
int
array_index
(
const
std
::
string
&
s
)
static
typename
BasicJsonType
::
size_type
array_index
(
const
std
::
string
&
s
)
{
{
using
size_type
=
typename
BasicJsonType
::
size_type
;
// error condition (cf. RFC 6901, Sect. 4)
// error condition (cf. RFC 6901, Sect. 4)
if
(
JSON_HEDLEY_UNLIKELY
(
s
.
size
()
>
1
and
s
[
0
]
==
'0'
))
if
(
JSON_HEDLEY_UNLIKELY
(
s
.
size
()
>
1
and
s
[
0
]
==
'0'
))
{
{
...
@@ -11380,10 +11386,10 @@ class json_pointer
...
@@ -11380,10 +11386,10 @@ class json_pointer
}
}
std
::
size_t
processed_chars
=
0
;
std
::
size_t
processed_chars
=
0
;
int
res
=
0
;
unsigned
long
long
res
=
0
;
JSON_TRY
JSON_TRY
{
{
res
=
std
::
sto
i
(
s
,
&
processed_chars
);
res
=
std
::
sto
ull
(
s
,
&
processed_chars
);
}
}
JSON_CATCH
(
std
::
out_of_range
&
)
JSON_CATCH
(
std
::
out_of_range
&
)
{
{
...
@@ -11396,7 +11402,14 @@ class json_pointer
...
@@ -11396,7 +11402,14 @@ class json_pointer
JSON_THROW
(
detail
::
out_of_range
::
create
(
404
,
"unresolved reference token '"
+
s
+
"'"
));
JSON_THROW
(
detail
::
out_of_range
::
create
(
404
,
"unresolved reference token '"
+
s
+
"'"
));
}
}
return
res
;
// only triggered on special platforms (like 32bit), see also
// https://github.com/nlohmann/json/pull/2203
if
(
res
>=
static_cast
<
unsigned
long
long
>
((
std
::
numeric_limits
<
size_type
>::
max
)()))
{
JSON_THROW
(
detail
::
out_of_range
::
create
(
410
,
"array index "
+
s
+
" exceeds size_type"
));
// LCOV_EXCL_LINE
}
return
static_cast
<
size_type
>
(
res
);
}
}
json_pointer
top
()
const
json_pointer
top
()
const
...
@@ -11455,7 +11468,7 @@ class json_pointer
...
@@ -11455,7 +11468,7 @@ class json_pointer
case
detail
:
:
value_t
::
array
:
case
detail
:
:
value_t
::
array
:
{
{
// create an entry in the array
// create an entry in the array
result
=
&
result
->
operator
[](
static_cast
<
size_type
>
(
array_index
(
reference_token
)
));
result
=
&
result
->
operator
[](
array_index
(
reference_token
));
break
;
break
;
}
}
...
@@ -11533,8 +11546,7 @@ class json_pointer
...
@@ -11533,8 +11546,7 @@ class json_pointer
else
else
{
{
// convert array index to number; unchecked access
// convert array index to number; unchecked access
ptr
=
&
ptr
->
operator
[](
ptr
=
&
ptr
->
operator
[](
array_index
(
reference_token
));
static_cast
<
size_type
>
(
array_index
(
reference_token
)));
}
}
break
;
break
;
}
}
...
@@ -11578,7 +11590,7 @@ class json_pointer
...
@@ -11578,7 +11590,7 @@ class json_pointer
}
}
// note: at performs range check
// note: at performs range check
ptr
=
&
ptr
->
at
(
static_cast
<
size_type
>
(
array_index
(
reference_token
)
));
ptr
=
&
ptr
->
at
(
array_index
(
reference_token
));
break
;
break
;
}
}
...
@@ -11628,8 +11640,7 @@ class json_pointer
...
@@ -11628,8 +11640,7 @@ class json_pointer
}
}
// use unchecked array access
// use unchecked array access
ptr
=
&
ptr
->
operator
[](
ptr
=
&
ptr
->
operator
[](
array_index
(
reference_token
));
static_cast
<
size_type
>
(
array_index
(
reference_token
)));
break
;
break
;
}
}
...
@@ -11672,7 +11683,7 @@ class json_pointer
...
@@ -11672,7 +11683,7 @@ class json_pointer
}
}
// note: at performs range check
// note: at performs range check
ptr
=
&
ptr
->
at
(
static_cast
<
size_type
>
(
array_index
(
reference_token
)
));
ptr
=
&
ptr
->
at
(
array_index
(
reference_token
));
break
;
break
;
}
}
...
@@ -11736,7 +11747,7 @@ class json_pointer
...
@@ -11736,7 +11747,7 @@ class json_pointer
}
}
}
}
const
auto
idx
=
static_cast
<
size_type
>
(
array_index
(
reference_token
)
);
const
auto
idx
=
array_index
(
reference_token
);
if
(
idx
>=
ptr
->
size
())
if
(
idx
>=
ptr
->
size
())
{
{
// index out of range
// index out of range
...
@@ -24001,7 +24012,7 @@ class basic_json
...
@@ -24001,7 +24012,7 @@ class basic_json
else
else
{
{
const
auto
idx
=
json_pointer
::
array_index
(
last_path
);
const
auto
idx
=
json_pointer
::
array_index
(
last_path
);
if
(
JSON_HEDLEY_UNLIKELY
(
static_cast
<
size_type
>
(
idx
)
>
parent
.
size
()))
if
(
JSON_HEDLEY_UNLIKELY
(
idx
>
parent
.
size
()))
{
{
// avoid undefined behavior
// avoid undefined behavior
JSON_THROW
(
out_of_range
::
create
(
401
,
"array index "
+
std
::
to_string
(
idx
)
+
" is out of range"
));
JSON_THROW
(
out_of_range
::
create
(
401
,
"array index "
+
std
::
to_string
(
idx
)
+
" is out of range"
));
...
@@ -24044,7 +24055,7 @@ class basic_json
...
@@ -24044,7 +24055,7 @@ class basic_json
else
if
(
parent
.
is_array
())
else
if
(
parent
.
is_array
())
{
{
// note erase performs range check
// note erase performs range check
parent
.
erase
(
static_cast
<
size_type
>
(
json_pointer
::
array_index
(
last_path
)
));
parent
.
erase
(
json_pointer
::
array_index
(
last_path
));
}
}
};
};
...
...
test/src/unit-json_pointer.cpp
View file @
4bfe4add
...
@@ -348,12 +348,29 @@ TEST_CASE("JSON pointers")
...
@@ -348,12 +348,29 @@ TEST_CASE("JSON pointers")
CHECK_THROWS_WITH
(
j_const
[
"/1+1"
_json_pointer
]
==
1
,
CHECK_THROWS_WITH
(
j_const
[
"/1+1"
_json_pointer
]
==
1
,
"[json.exception.out_of_range.404] unresolved reference token '1+1'"
);
"[json.exception.out_of_range.404] unresolved reference token '1+1'"
);
CHECK_THROWS_AS
(
j
[
"/111111111111111111111111"
_json_pointer
]
=
1
,
json
::
out_of_range
&
);
{
CHECK_THROWS_WITH
(
j
[
"/111111111111111111111111"
_json_pointer
]
=
1
,
auto
too_large_index
=
std
::
to_string
((
std
::
numeric_limits
<
unsigned
long
long
>::
max
)())
+
"1"
;
"[json.exception.out_of_range.404] unresolved reference token '111111111111111111111111'"
);
json
::
json_pointer
jp
(
std
::
string
(
"/"
)
+
too_large_index
);
CHECK_THROWS_AS
(
j_const
[
"/111111111111111111111111"
_json_pointer
]
==
1
,
json
::
out_of_range
&
);
std
::
string
throw_msg
=
std
::
string
(
"[json.exception.out_of_range.404] unresolved reference token '"
)
+
too_large_index
+
"'"
;
CHECK_THROWS_WITH
(
j_const
[
"/111111111111111111111111"
_json_pointer
]
==
1
,
"[json.exception.out_of_range.404] unresolved reference token '111111111111111111111111'"
);
CHECK_THROWS_AS
(
j
[
jp
]
=
1
,
json
::
out_of_range
&
);
CHECK_THROWS_WITH
(
j
[
jp
]
=
1
,
throw_msg
.
c_str
());
CHECK_THROWS_AS
(
j_const
[
jp
]
==
1
,
json
::
out_of_range
&
);
CHECK_THROWS_WITH
(
j_const
[
jp
]
==
1
,
throw_msg
.
c_str
());
}
if
(
sizeof
(
typename
json
::
size_type
)
<
sizeof
(
unsigned
long
long
))
{
auto
size_type_max_uul
=
static_cast
<
unsigned
long
long
>
((
std
::
numeric_limits
<
json
::
size_type
>::
max
)());
auto
too_large_index
=
std
::
to_string
(
size_type_max_uul
);
json
::
json_pointer
jp
(
std
::
string
(
"/"
)
+
too_large_index
);
std
::
string
throw_msg
=
std
::
string
(
"[json.exception.out_of_range.410] array index "
)
+
too_large_index
+
" exceeds size_type"
;
CHECK_THROWS_AS
(
j
[
jp
]
=
1
,
json
::
out_of_range
&
);
CHECK_THROWS_WITH
(
j
[
jp
]
=
1
,
throw_msg
.
c_str
());
CHECK_THROWS_AS
(
j_const
[
jp
]
==
1
,
json
::
out_of_range
&
);
CHECK_THROWS_WITH
(
j_const
[
jp
]
==
1
,
throw_msg
.
c_str
());
}
CHECK_THROWS_AS
(
j
.
at
(
"/one"
_json_pointer
)
=
1
,
json
::
parse_error
&
);
CHECK_THROWS_AS
(
j
.
at
(
"/one"
_json_pointer
)
=
1
,
json
::
parse_error
&
);
CHECK_THROWS_WITH
(
j
.
at
(
"/one"
_json_pointer
)
=
1
,
CHECK_THROWS_WITH
(
j
.
at
(
"/one"
_json_pointer
)
=
1
,
...
...
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