Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
607dbbf5
Commit
607dbbf5
authored
Nov 20, 2015
by
Kenton Varda
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #258 from kamalmarhubi/json-decodeRaw
Implement most of JsonCodec::decodeRaw
parents
e93c9aca
f60fe3c2
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
294 additions
and
0 deletions
+294
-0
CONTRIBUTORS
CONTRIBUTORS
+1
-0
json-test.c++
c++/src/capnp/compat/json-test.c++
+289
-0
json.c++
c++/src/capnp/compat/json.c++
+0
-0
json.h
c++/src/capnp/compat/json.h
+4
-0
No files found.
CONTRIBUTORS
View file @
607dbbf5
...
...
@@ -11,6 +11,7 @@ Bryan Borham <bjboreham@gmail.com>: Initial MSVC support
Philip Quinn <p@partylemon.com>: cmake build and other assorted bits
Brian Taylor <el.wubo@gmail.com>: emacs syntax highlighting
Ben Laurie <ben@links.org>: discovered and responsibly disclosed security bugs
Kamal Marhubi <kamal@marhubi.com>: JSON parser
This file does not list people who maintain their own Cap'n Proto
implementations as separate projects. Those people are awesome too! :)
c++/src/capnp/compat/json-test.c++
View file @
607dbbf5
...
...
@@ -21,7 +21,9 @@
#include "json.h"
#include <capnp/test-util.h>
#include <capnp/compat/json.capnp.h>
#include <kj/debug.h>
#include <kj/string.h>
#include <kj/test.h>
namespace
capnp
{
...
...
@@ -181,6 +183,293 @@ KJ_TEST("encode union") {
KJ_EXPECT
(
json
.
encode
(
root
)
==
"{
\"
before
\"
:
\"
a
\"
,
\"
middle
\"
:44,
\"
bar
\"
:321,
\"
after
\"
:
\"
c
\"
}"
);
}
KJ_TEST
(
"basic json decoding"
)
{
// TODO(cleanup): this test is a mess!
JsonCodec
json
;
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"null"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
NULL_
);
KJ_EXPECT
(
root
.
getNull
()
==
VOID
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"false"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
BOOLEAN
);
KJ_EXPECT
(
root
.
getBoolean
()
==
false
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"true"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
BOOLEAN
);
KJ_EXPECT
(
root
.
getBoolean
()
==
true
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"
\"
foo
\"
"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
STRING
);
KJ_EXPECT
(
kj
::
str
(
"foo"
)
==
root
.
getString
());
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
R"("\"")"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
STRING
);
KJ_EXPECT
(
kj
::
str
(
"
\"
"
)
==
root
.
getString
());
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
R"("\\abc\"d\\e")"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
STRING
);
KJ_EXPECT
(
kj
::
str
(
"
\\
abc
\"
d
\\
e"
)
==
root
.
getString
());
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
R"("\"\\\/\b\f\n\r\t\u0003abc\u0064\u0065f")"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
STRING
);
KJ_EXPECT
(
kj
::
str
(
"
\"\\
/
\b\f\n\r\t\x03
""abcdef"
)
==
root
.
getString
(),
root
.
getString
());
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"[]"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
ARRAY
,
root
.
which
());
KJ_EXPECT
(
root
.
getArray
().
size
()
==
0
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"[true]"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
ARRAY
);
auto
array
=
root
.
getArray
();
KJ_EXPECT
(
array
.
size
()
==
1
,
array
.
size
());
KJ_EXPECT
(
root
.
getArray
()[
0
].
which
()
==
JsonValue
::
BOOLEAN
);
KJ_EXPECT
(
root
.
getArray
()[
0
].
getBoolean
()
==
true
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
" [ true , false
\t\n
, null]"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
ARRAY
);
auto
array
=
root
.
getArray
();
KJ_EXPECT
(
array
.
size
()
==
3
);
KJ_EXPECT
(
array
[
0
].
which
()
==
JsonValue
::
BOOLEAN
);
KJ_EXPECT
(
array
[
0
].
getBoolean
()
==
true
);
KJ_EXPECT
(
array
[
1
].
which
()
==
JsonValue
::
BOOLEAN
);
KJ_EXPECT
(
array
[
1
].
getBoolean
()
==
false
);
KJ_EXPECT
(
array
[
2
].
which
()
==
JsonValue
::
NULL_
);
KJ_EXPECT
(
array
[
2
].
getNull
()
==
VOID
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"{}"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
OBJECT
,
root
.
which
());
KJ_EXPECT
(
root
.
getObject
().
size
()
==
0
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
R"({"some": null})"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
OBJECT
,
root
.
which
());
auto
object
=
root
.
getObject
();
KJ_EXPECT
(
object
.
size
()
==
1
);
KJ_EXPECT
(
kj
::
str
(
"some"
)
==
object
[
0
].
getName
());
KJ_EXPECT
(
object
[
0
].
getValue
().
which
()
==
JsonValue
::
NULL_
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
R"({"foo\n\tbaz": "a val", "bar": ["a", -5.5e11, { "z": {}}]})"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
OBJECT
,
root
.
which
());
auto
object
=
root
.
getObject
();
KJ_EXPECT
(
object
.
size
()
==
2
);
KJ_EXPECT
(
kj
::
str
(
"foo
\n\t
baz"
)
==
object
[
0
].
getName
());
KJ_EXPECT
(
object
[
0
].
getValue
().
which
()
==
JsonValue
::
STRING
);
KJ_EXPECT
(
kj
::
str
(
"a val"
)
==
object
[
0
].
getValue
().
getString
());
KJ_EXPECT
(
kj
::
str
(
"bar"
)
==
object
[
1
].
getName
());
KJ_EXPECT
(
object
[
1
].
getValue
().
which
()
==
JsonValue
::
ARRAY
);
auto
array
=
object
[
1
].
getValue
().
getArray
();
KJ_EXPECT
(
array
.
size
()
==
3
,
array
.
size
());
KJ_EXPECT
(
array
[
0
].
which
()
==
JsonValue
::
STRING
);
KJ_EXPECT
(
kj
::
str
(
"a"
)
==
array
[
0
].
getString
());
KJ_EXPECT
(
array
[
1
].
which
()
==
JsonValue
::
NUMBER
);
KJ_EXPECT
(
array
[
1
].
getNumber
()
==
-
5.5e11
);
KJ_EXPECT
(
array
[
2
].
which
()
==
JsonValue
::
OBJECT
);
KJ_EXPECT
(
array
[
2
].
getObject
().
size
()
==
1
);
KJ_EXPECT
(
array
[
2
].
getObject
()[
0
].
getValue
().
which
()
==
JsonValue
::
OBJECT
);
KJ_EXPECT
(
array
[
2
].
getObject
()[
0
].
getValue
().
getObject
().
size
()
==
0
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"123"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
NUMBER
);
KJ_EXPECT
(
root
.
getNumber
()
==
123
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"input"
,
json
.
decodeRaw
(
"z"
,
root
));
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
// Leading + not allowed in numbers.
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected"
,
json
.
decodeRaw
(
"+123"
,
root
));
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"Overflow"
,
json
.
decodeRaw
(
"1e1024"
,
root
));
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"Underflow"
,
json
.
decodeRaw
(
"1e-1023"
,
root
));
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected"
,
json
.
decodeRaw
(
"[00]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected"
,
json
.
decodeRaw
(
"[01]"
,
root
));
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"ends prematurely"
,
json
.
decodeRaw
(
"-"
,
root
));
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"-5"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
NUMBER
);
KJ_EXPECT
(
root
.
getNumber
()
==
-
5
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
"-5.5"
,
root
);
KJ_EXPECT
(
root
.
which
()
==
JsonValue
::
NUMBER
);
KJ_EXPECT
(
root
.
getNumber
()
==
-
5.5
);
}
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"a"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"ends prematurely"
,
json
.
decodeRaw
(
"["
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"ends prematurely"
,
json
.
decodeRaw
(
"{"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[}"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"{]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[}]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[1, , ]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[,]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[true,]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[, 1]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[1
\"\"
]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"[1,,
\"\"
]"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"{
\"
a
\"
1: 0}"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
R"({"some": null,})"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Input remains"
,
json
.
decodeRaw
(
"11a"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Invalid escape"
,
json
.
decodeRaw
(
R"("\z")"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Invalid escape"
,
json
.
decodeRaw
(
R"("\z")"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"ends prematurely"
,
json
.
decodeRaw
(
R"(["\n\", 3])"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Invalid hex"
,
json
.
decodeRaw
(
R"("\u12zz")"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"ends prematurely"
,
json
.
decodeRaw
(
"-"
,
root
));
KJ_EXPECT_THROW_MESSAGE
(
"Unexpected input"
,
json
.
decodeRaw
(
"--"
,
root
));
}
}
KJ_TEST
(
"maximum nesting depth"
)
{
JsonCodec
json
;
auto
input
=
kj
::
str
(
R"({"foo": "a", "bar": ["b", { "baz": [-5.5e11] }, [ [ 1 ], { "z": 2 }]]})"
);
// `input` has a maximum nesting depth of 4, reached 3 times.
{
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
input
,
root
);
}
{
json
.
setMaxNestingDepth
(
0
);
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"nest"
,
json
.
decodeRaw
(
input
,
root
));
}
{
json
.
setMaxNestingDepth
(
3
);
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
KJ_EXPECT_THROW_MESSAGE
(
"nest"
,
json
.
decodeRaw
(
input
,
root
));
}
{
json
.
setMaxNestingDepth
(
4
);
MallocMessageBuilder
message
;
auto
root
=
message
.
initRoot
<
JsonValue
>
();
json
.
decodeRaw
(
input
,
root
);
}
}
class
TestHandler
:
public
JsonCodec
::
Handler
<
Text
>
{
public
:
void
encode
(
const
JsonCodec
&
codec
,
Text
::
Reader
input
,
...
...
c++/src/capnp/compat/json.c++
View file @
607dbbf5
This diff is collapsed.
Click to expand it.
c++/src/capnp/compat/json.h
View file @
607dbbf5
...
...
@@ -71,6 +71,10 @@ public:
// Enable to insert newlines, indentation, and other extra spacing into the output. The default
// is to use minimal whitespace.
void
setMaxNestingDepth
(
size_t
maxNestingDepth
);
// Set maximum nesting depth when decoding JSON to prevent highly nested input from overflowing
// the call stack. The default is 64.
template
<
typename
T
>
kj
::
String
encode
(
T
&&
value
);
// Encode any Cap'n Proto value to JSON, including primitives and
...
...
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