diff options
-rw-r--r-- | src/rpcclient.cpp | 36 | ||||
-rw-r--r-- | src/rpcclient.h | 4 | ||||
-rw-r--r-- | src/test/rpc_tests.cpp | 23 |
3 files changed, 30 insertions, 33 deletions
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index d175db09ee..f254da5de0 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -121,6 +121,18 @@ CRPCConvertTable::CRPCConvertTable() static CRPCConvertTable rpcCvtTable; +/** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null) + * as well as objects and arrays. + */ +UniValue ParseNonRFCJSONValue(const std::string& strVal) +{ + UniValue jVal; + if (!jVal.read(std::string("[")+strVal+std::string("]")) || + !jVal.isArray() || jVal.size()!=1) + throw runtime_error(string("Error parsing JSON:")+strVal); + return jVal[0]; +} + /** Convert strings to command-specific RPC representation */ UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams) { @@ -129,28 +141,12 @@ UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::s for (unsigned int idx = 0; idx < strParams.size(); idx++) { const std::string& strVal = strParams[idx]; - // insert string value directly if (!rpcCvtTable.convert(strMethod, idx)) { + // insert string value directly params.push_back(strVal); - } - - // parse string as JSON, insert bool/number/object/etc. value - else { - //according to rfc4627 null, true, false are not valid json strings - UniValue jVal; - if(strVal == "null") - jVal.setNull(); - else if(strVal == "true") - jVal.setBool(true); - else if(strVal == "false") - jVal.setBool(false); - else - { - if (!jVal.read(strVal) || (jVal.isNull() && strVal.size() > 0)) - if(!jVal.setNumStr(strVal) || jVal.isNull()) - throw runtime_error(string("Error parsing JSON:")+strVal); - } - params.push_back(jVal); + } else { + // parse string as JSON, insert bool/number/object/etc. value + params.push_back(ParseNonRFCJSONValue(strVal)); } } diff --git a/src/rpcclient.h b/src/rpcclient.h index 52270aec74..d68b4ed6ae 100644 --- a/src/rpcclient.h +++ b/src/rpcclient.h @@ -9,5 +9,9 @@ #include "univalue/univalue.h" UniValue RPCConvertValues(const std::string& strMethod, const std::vector<std::string>& strParams); +/** Non-RFC4627 JSON parser, accepts internal values (such as numbers, true, false, null) + * as well as objects and arrays. + */ +UniValue ParseNonRFCJSONValue(const std::string& strVal); #endif // BITCOIN_RPCCLIENT_H diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 576e62a0bb..0b33ddb086 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -143,23 +143,20 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values) BOOST_AUTO_TEST_CASE(json_parse_errors) { - UniValue value; // Valid - BOOST_CHECK_EQUAL(value.read(std::string("1.0")), false); - BOOST_CHECK_EQUAL(value.read(std::string("[1.0]")), true); - // Valid, with trailing whitespace - BOOST_CHECK_EQUAL(value.read(std::string("1.0 ")), false); - BOOST_CHECK_EQUAL(value.read(std::string("[1.0 ] ")), true); + BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0").get_real(), 1.0); + // Valid, with leading or trailing whitespace + BOOST_CHECK_EQUAL(ParseNonRFCJSONValue(" 1.0").get_real(), 1.0); + BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0 ").get_real(), 1.0); // Invalid, initial garbage - BOOST_CHECK_EQUAL(value.read(std::string("[1.0")), false); - BOOST_CHECK_EQUAL(value.read(std::string("[a1.0]")), false); - BOOST_CHECK_EQUAL(value.read(std::string("[\"a1.0\"]")), true); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("[1.0"), std::runtime_error); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("a1.0"), std::runtime_error); // Invalid, trailing garbage - BOOST_CHECK_EQUAL(value.read(std::string("1.0sds")), false); - BOOST_CHECK_EQUAL(value.read(std::string("1.0]")), false); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0sds"), std::runtime_error); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0]"), std::runtime_error); // BTC addresses should fail parsing - BOOST_CHECK_EQUAL(value.read(std::string("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")), false); - BOOST_CHECK_EQUAL(value.read(std::string("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL")), false); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"), std::runtime_error); + BOOST_CHECK_THROW(ParseNonRFCJSONValue("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"), std::runtime_error); } BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr) |