Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
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
Operations
Operations
Metrics
Environments
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
cpp-libs
Actor Framework
Commits
a22c0b2a
Commit
a22c0b2a
authored
Aug 03, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/neverlord/json-fix'
parents
846503b3
0904018c
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
43 additions
and
13 deletions
+43
-13
CHANGELOG.md
CHANGELOG.md
+2
-0
libcaf_core/caf/pec.hpp
libcaf_core/caf/pec.hpp
+2
-0
libcaf_core/src/detail/json.cpp
libcaf_core/src/detail/json.cpp
+39
-13
No files found.
CHANGELOG.md
View file @
a22c0b2a
...
...
@@ -18,6 +18,8 @@ is based on [Keep a Changelog](https://keepachangelog.com).
-
Fix undefined behavior in the Qt group chat example (#1336).
-
The
`..._instance`
convenience functions on the registry metric now properly
support
`double`
metrics and histograms.
-
Parsing deeply nested JSON inputs no longer produces a stack overflow.
Instead, the parser rejects any JSON with too many nesting levels.
### Changed
...
...
libcaf_core/caf/pec.hpp
View file @
a22c0b2a
...
...
@@ -66,6 +66,8 @@ enum class pec : uint8_t {
/// Stopped after running into an invalid parser state. Should never happen
/// and most likely indicates a bug in the implementation.
invalid_state
,
/// Parser stopped after exceeding its maximum supported level of nesting.
nested_too_deeply
,
};
/// @relates pec
...
...
libcaf_core/src/detail/json.cpp
View file @
a22c0b2a
...
...
@@ -19,6 +19,12 @@ CAF_PUSH_UNUSED_LABEL_WARNING
#include "caf/detail/parser/fsm.hpp"
namespace
{
constexpr
size_t
max_nesting_level
=
128
;
}
// namespace
namespace
caf
::
detail
::
parser
{
struct
obj_consumer
;
...
...
@@ -93,7 +99,8 @@ obj_consumer val_consumer::begin_object() {
return
{
&
obj
};
}
void
read_value
(
string_parser_state
&
ps
,
val_consumer
consumer
);
void
read_value
(
string_parser_state
&
ps
,
size_t
nesting_level
,
val_consumer
consumer
);
template
<
class
Consumer
>
void
read_json_null_or_nan
(
string_parser_state
&
ps
,
Consumer
consumer
)
{
...
...
@@ -161,7 +168,8 @@ void read_json_string(string_parser_state& ps, Consumer consumer) {
// clang-format on
}
void
read_member
(
string_parser_state
&
ps
,
member_consumer
consumer
)
{
void
read_member
(
string_parser_state
&
ps
,
size_t
nesting_level
,
member_consumer
consumer
)
{
// clang-format off
start
();
state
(
init
)
{
...
...
@@ -170,7 +178,8 @@ void read_member(string_parser_state& ps, member_consumer consumer) {
}
state
(
after_key
)
{
transition
(
after_key
,
"
\t\n
"
)
fsm_transition
(
read_value
(
ps
,
consumer
.
begin_val
()),
done
,
':'
)
fsm_transition
(
read_value
(
ps
,
nesting_level
,
consumer
.
begin_val
()),
done
,
':'
)
}
term_state
(
done
)
{
transition
(
done
,
"
\t\n
"
)
...
...
@@ -179,7 +188,12 @@ void read_member(string_parser_state& ps, member_consumer consumer) {
// clang-format on
}
void
read_json_object
(
string_parser_state
&
ps
,
obj_consumer
consumer
)
{
void
read_json_object
(
string_parser_state
&
ps
,
size_t
nesting_level
,
obj_consumer
consumer
)
{
if
(
nesting_level
>=
max_nesting_level
)
{
ps
.
code
=
pec
::
nested_too_deeply
;
return
;
}
// clang-format off
start
();
state
(
init
)
{
...
...
@@ -188,7 +202,8 @@ void read_json_object(string_parser_state& ps, obj_consumer consumer) {
}
state
(
has_open_brace
)
{
transition
(
has_open_brace
,
"
\t\n
"
)
fsm_epsilon
(
read_member
(
ps
,
consumer
.
begin_member
()),
after_member
,
'"'
)
fsm_epsilon
(
read_member
(
ps
,
nesting_level
+
1
,
consumer
.
begin_member
()),
after_member
,
'"'
)
transition
(
done
,
'}'
)
}
state
(
after_member
)
{
...
...
@@ -198,7 +213,8 @@ void read_json_object(string_parser_state& ps, obj_consumer consumer) {
}
state
(
after_comma
)
{
transition
(
after_comma
,
"
\t\n
"
)
fsm_epsilon
(
read_member
(
ps
,
consumer
.
begin_member
()),
after_member
,
'"'
)
fsm_epsilon
(
read_member
(
ps
,
nesting_level
+
1
,
consumer
.
begin_member
()),
after_member
,
'"'
)
}
term_state
(
done
)
{
transition
(
done
,
"
\t\n
"
)
...
...
@@ -207,7 +223,12 @@ void read_json_object(string_parser_state& ps, obj_consumer consumer) {
// clang-format on
}
void
read_json_array
(
string_parser_state
&
ps
,
arr_consumer
consumer
)
{
void
read_json_array
(
string_parser_state
&
ps
,
size_t
nesting_level
,
arr_consumer
consumer
)
{
if
(
nesting_level
>=
max_nesting_level
)
{
ps
.
code
=
pec
::
nested_too_deeply
;
return
;
}
// clang-format off
start
();
state
(
init
)
{
...
...
@@ -217,7 +238,8 @@ void read_json_array(string_parser_state& ps, arr_consumer consumer) {
state
(
has_open_brace
)
{
transition
(
has_open_brace
,
"
\t\n
"
)
transition
(
done
,
']'
)
fsm_epsilon
(
read_value
(
ps
,
consumer
.
begin_value
()),
after_value
)
fsm_epsilon
(
read_value
(
ps
,
nesting_level
+
1
,
consumer
.
begin_value
()),
after_value
)
}
state
(
after_value
)
{
transition
(
after_value
,
"
\t\n
"
)
...
...
@@ -226,7 +248,8 @@ void read_json_array(string_parser_state& ps, arr_consumer consumer) {
}
state
(
after_comma
)
{
transition
(
after_comma
,
"
\t\n
"
)
fsm_epsilon
(
read_value
(
ps
,
consumer
.
begin_value
()),
after_value
)
fsm_epsilon
(
read_value
(
ps
,
nesting_level
+
1
,
consumer
.
begin_value
()),
after_value
)
}
term_state
(
done
)
{
transition
(
done
,
"
\t\n
"
)
...
...
@@ -235,7 +258,8 @@ void read_json_array(string_parser_state& ps, arr_consumer consumer) {
// clang-format on
}
void
read_value
(
string_parser_state
&
ps
,
val_consumer
consumer
)
{
void
read_value
(
string_parser_state
&
ps
,
size_t
nesting_level
,
val_consumer
consumer
)
{
// clang-format off
start
();
state
(
init
)
{
...
...
@@ -244,8 +268,10 @@ void read_value(string_parser_state& ps, val_consumer consumer) {
fsm_epsilon
(
read_bool
(
ps
,
consumer
),
done
,
"ft"
)
fsm_epsilon
(
read_json_null_or_nan
(
ps
,
consumer
),
done
,
"n"
)
fsm_epsilon
(
read_number
(
ps
,
consumer
),
done
,
"+-.0123456789"
)
fsm_epsilon
(
read_json_object
(
ps
,
consumer
.
begin_object
()),
done
,
'{'
)
fsm_epsilon
(
read_json_array
(
ps
,
consumer
.
begin_array
()),
done
,
'['
)
fsm_epsilon
(
read_json_object
(
ps
,
nesting_level
,
consumer
.
begin_object
()),
done
,
'{'
)
fsm_epsilon
(
read_json_array
(
ps
,
nesting_level
,
consumer
.
begin_array
()),
done
,
'['
)
}
term_state
(
done
)
{
transition
(
done
,
"
\t\n
"
)
...
...
@@ -300,7 +326,7 @@ object* make_object(monotonic_buffer_resource* storage) {
value
*
parse
(
string_parser_state
&
ps
,
monotonic_buffer_resource
*
storage
)
{
monotonic_buffer_resource
::
allocator
<
value
>
alloc
{
storage
};
auto
result
=
new
(
alloc
.
allocate
(
1
))
value
();
parser
::
read_value
(
ps
,
{
storage
,
result
});
parser
::
read_value
(
ps
,
0
,
{
storage
,
result
});
return
result
;
}
...
...
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