aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kraft <d@domob.eu>2015-08-20 12:48:43 +0200
committerDaniel Kraft <d@domob.eu>2015-08-20 12:48:43 +0200
commite938122b7ba8723c8cab6de78e8a9b39ad188589 (patch)
tree8dc918238e08377ef3ccac660f8fd935e562e31e
parentef30389e2a4a83c2845a2cbdf3a7c2f062404077 (diff)
Stop parsing JSON after first finished construct.
Fix https://github.com/bitcoin/bitcoin/issues/6558. In particular, stop parsing JSON after the first object or array is finished. Check that no other garbage follows, and fail the parser if it does.
-rw-r--r--src/test/univalue_tests.cpp15
-rw-r--r--src/univalue/univalue_read.cpp14
2 files changed, 23 insertions, 6 deletions
diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp
index 67cb9b9623..ee31c0955b 100644
--- a/src/test/univalue_tests.cpp
+++ b/src/test/univalue_tests.cpp
@@ -314,6 +314,21 @@ BOOST_AUTO_TEST_CASE(univalue_readwrite)
BOOST_CHECK(obj["key3"].isObject());
BOOST_CHECK_EQUAL(strJson1, v.write());
+
+ /* Check for (correctly reporting) a parsing error if the initial
+ JSON construct is followed by more stuff. Note that whitespace
+ is, of course, exempt. */
+
+ BOOST_CHECK(v.read(" {}\n "));
+ BOOST_CHECK(v.isObject());
+ BOOST_CHECK(v.read(" []\n "));
+ BOOST_CHECK(v.isArray());
+
+ BOOST_CHECK(!v.read("@{}"));
+ BOOST_CHECK(!v.read("{} garbage"));
+ BOOST_CHECK(!v.read("[]{}"));
+ BOOST_CHECK(!v.read("{}[]"));
+ BOOST_CHECK(!v.read("{} 42"));
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/univalue/univalue_read.cpp b/src/univalue/univalue_read.cpp
index 261771811d..64591234cb 100644
--- a/src/univalue/univalue_read.cpp
+++ b/src/univalue/univalue_read.cpp
@@ -244,16 +244,16 @@ bool UniValue::read(const char *raw)
bool expectColon = false;
vector<UniValue*> stack;
+ string tokenVal;
+ unsigned int consumed;
enum jtokentype tok = JTOK_NONE;
enum jtokentype last_tok = JTOK_NONE;
- while (1) {
+ do {
last_tok = tok;
- string tokenVal;
- unsigned int consumed;
tok = getJsonToken(tokenVal, consumed, raw);
if (tok == JTOK_NONE || tok == JTOK_ERR)
- break;
+ return false;
raw += consumed;
switch (tok) {
@@ -377,9 +377,11 @@ bool UniValue::read(const char *raw)
default:
return false;
}
- }
+ } while (!stack.empty ());
- if (stack.size() != 0)
+ /* Check that nothing follows the initial construct (parsed above). */
+ tok = getJsonToken(tokenVal, consumed, raw);
+ if (tok != JTOK_NONE)
return false;
return true;