Implement missing string conversions for JSON

`Json::Value::isConvertibleTo` indicates that unsigned integers and
reals are convertible to string, but trying to do so (with
`Json::Value::asString`) throws an exception because its internal switch
is missing these cases. This change fills them in (and adds tests).

Acknowledgements:
Ripple thanks Guido Vranken for responsibly disclosing this issue.

Closes #2778
This commit is contained in:
John Freeman
2018-11-19 12:36:02 -06:00
parent cc824685e7
commit c0e9418fc7
3 changed files with 43 additions and 0 deletions

View File

@@ -523,7 +523,11 @@ Value::asString () const
return beast::lexicalCastThrow <std::string> (value_.int_); return beast::lexicalCastThrow <std::string> (value_.int_);
case uintValue: case uintValue:
return beast::lexicalCastThrow <std::string> (value_.uint_);
case realValue: case realValue:
return beast::lexicalCastThrow <std::string> (value_.real_);
case arrayValue: case arrayValue:
case objectValue: case objectValue:
JSON_ASSERT_MESSAGE ( false, "Type is not convertible to string" ); JSON_ASSERT_MESSAGE ( false, "Type is not convertible to string" );

View File

@@ -246,12 +246,14 @@ public:
ValueType type () const; ValueType type () const;
const char* asCString () const; const char* asCString () const;
/** Returns the unquoted string value. */
std::string asString () const; std::string asString () const;
Int asInt () const; Int asInt () const;
UInt asUInt () const; UInt asUInt () const;
double asDouble () const; double asDouble () const;
bool asBool () const; bool asBool () const;
// TODO: What is the "empty()" method this docstring mentions?
/** isNull() tests to see if this field is null. Don't use this method to /** isNull() tests to see if this field is null. Don't use this method to
test for emptiness: use empty(). */ test for emptiness: use empty(). */
bool isNull () const; bool isNull () const;

View File

@@ -24,6 +24,7 @@
#include <ripple/beast/type_name.h> #include <ripple/beast/type_name.h>
#include <algorithm> #include <algorithm>
#include <regex>
namespace ripple { namespace ripple {
@@ -250,6 +251,41 @@ struct json_value_test : beast::unit_test::suite
} }
} }
void test_conversions ()
{
// We have Json::Int, but not Json::Double or Json::Real.
// We have Json::Int, Json::Value::Int, and Json::ValueType::intValue.
// We have Json::ValueType::realValue but Json::Value::asDouble.
// TODO: What's the thinking here?
{
// null
Json::Value val;
BEAST_EXPECT(val.isNull());
BEAST_EXPECT(val.asString() == "");
}
{
// bool
Json::Value val = true;
BEAST_EXPECT(val.asString() == "true");
}
{
// int
Json::Value val = -1234;
BEAST_EXPECT(val.asString() == "-1234");
}
{
// uint
Json::Value val = 1234U;
BEAST_EXPECT(val.asString() == "1234");
}
{
// real
Json::Value val = 2.0;
BEAST_EXPECT(std::regex_match(
val.asString(), std::regex("^2\\.0*$")));
}
}
void test_nest_limits () void test_nest_limits ()
{ {
Json::Reader r; Json::Reader r;
@@ -316,6 +352,7 @@ struct json_value_test : beast::unit_test::suite
test_move (); test_move ();
test_comparisons (); test_comparisons ();
test_compact (); test_compact ();
test_conversions();
test_nest_limits (); test_nest_limits ();
test_leak(); test_leak();
} }