mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-25 01:19:06 +02:00
Fix JSON parsing of large unsigned 64-bit integers
This commit is contained in:
parent
ae26e45bad
commit
13a1a0b9a2
@ -108,11 +108,17 @@ public:
|
|||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
virtual Int64 asInteger64() const;
|
virtual Int64 asInteger64() const;
|
||||||
/// Returns a 64-bit integer representation of the token.
|
/// Returns a 64-bit integer representation of the token.
|
||||||
|
|
||||||
|
virtual UInt64 asUnsignedInteger64() const;
|
||||||
|
/// Returns an unsigned 64-bit integer representation of the token.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual int asInteger() const;
|
virtual int asInteger() const;
|
||||||
/// Returns an integer representation of the token.
|
/// Returns an integer representation of the token.
|
||||||
|
|
||||||
|
virtual unsigned asUnsignedInteger() const;
|
||||||
|
/// Returns an unsigned integer representation of the token.
|
||||||
|
|
||||||
virtual double asFloat() const;
|
virtual double asFloat() const;
|
||||||
/// Returns a floating-point representation of the token.
|
/// Returns a floating-point representation of the token.
|
||||||
|
|
||||||
|
@ -81,6 +81,12 @@ Int64 Token::asInteger64() const
|
|||||||
{
|
{
|
||||||
return NumberParser::parse64(_value);
|
return NumberParser::parse64(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UInt64 Token::asUnsignedInteger64() const
|
||||||
|
{
|
||||||
|
return NumberParser::parseUnsigned64(_value);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -90,6 +96,12 @@ int Token::asInteger() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned Token::asUnsignedInteger() const
|
||||||
|
{
|
||||||
|
return NumberParser::parseUnsigned(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double Token::asFloat() const
|
double Token::asFloat() const
|
||||||
{
|
{
|
||||||
return NumberParser::parseFloat(_value);
|
return NumberParser::parseFloat(_value);
|
||||||
|
@ -82,9 +82,17 @@ public:
|
|||||||
virtual void value(int v);
|
virtual void value(int v);
|
||||||
/// An integer value is read
|
/// An integer value is read
|
||||||
|
|
||||||
|
virtual void value(unsigned v);
|
||||||
|
/// An unsigned value is read. This will only be triggered if the
|
||||||
|
/// value cannot fit into a signed int.
|
||||||
|
|
||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
virtual void value(Int64 v);
|
virtual void value(Int64 v);
|
||||||
/// A 64-bit integer value is read
|
/// A 64-bit integer value is read
|
||||||
|
|
||||||
|
virtual void value(UInt64 v);
|
||||||
|
/// An unsigned 64-bit integer value is read. This will only be
|
||||||
|
/// triggered if the value cannot fit into a signed 64-bit integer.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void value(const std::string& s);
|
virtual void value(const std::string& s);
|
||||||
@ -120,11 +128,23 @@ inline void DefaultHandler::value(int v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void DefaultHandler::value(unsigned v)
|
||||||
|
{
|
||||||
|
setValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
inline void DefaultHandler::value(Int64 v)
|
inline void DefaultHandler::value(Int64 v)
|
||||||
{
|
{
|
||||||
setValue(v);
|
setValue(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void DefaultHandler::value(UInt64 v)
|
||||||
|
{
|
||||||
|
setValue(v);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,9 +72,17 @@ public:
|
|||||||
virtual void value(int v) = 0;
|
virtual void value(int v) = 0;
|
||||||
/// An integer value is read
|
/// An integer value is read
|
||||||
|
|
||||||
|
virtual void value(unsigned v) = 0;
|
||||||
|
/// An unsigned value is read. This will only be triggered if the
|
||||||
|
/// value cannot fit into a signed int.
|
||||||
|
|
||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
virtual void value(Int64 v) = 0;
|
virtual void value(Int64 v) = 0;
|
||||||
/// A 64-bit integer value is read
|
/// A 64-bit integer value is read
|
||||||
|
|
||||||
|
virtual void value(UInt64 v) = 0;
|
||||||
|
/// An unsigned 64-bit integer value is read. This will only be
|
||||||
|
/// triggered if the value cannot fit into a signed 64-bit integer.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void value(const std::string& value) = 0;
|
virtual void value(const std::string& value) = 0;
|
||||||
|
@ -636,20 +636,46 @@ void Parser::readValue(const Token* token)
|
|||||||
if (_handler != NULL)
|
if (_handler != NULL)
|
||||||
{
|
{
|
||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
Int64 value = token->asInteger64();
|
try
|
||||||
// if number is 32-bit, then handle as such
|
{
|
||||||
if (value > std::numeric_limits<int>::max()
|
Int64 value = token->asInteger64();
|
||||||
|| value < std::numeric_limits<int>::min())
|
// if number is 32-bit, then handle as such
|
||||||
{
|
if ( value > std::numeric_limits<int>::max()
|
||||||
_handler->value(value);
|
|| value < std::numeric_limits<int>::min() )
|
||||||
}
|
{
|
||||||
else
|
_handler->value(value);
|
||||||
{
|
}
|
||||||
_handler->value(static_cast<int>(value));
|
else
|
||||||
}
|
{
|
||||||
|
_handler->value(static_cast<int>(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// try to handle error as unsigned in case of overflow
|
||||||
|
catch ( const SyntaxException& )
|
||||||
|
{
|
||||||
|
UInt64 value = token->asUnsignedInteger64();
|
||||||
|
// if number is 32-bit, then handle as such
|
||||||
|
if ( value > std::numeric_limits<unsigned>::max() )
|
||||||
|
{
|
||||||
|
_handler->value(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_handler->value(static_cast<unsigned>(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
int value = token->asInteger();
|
try
|
||||||
_handle->value(value);
|
{
|
||||||
|
int value = token->asInteger();
|
||||||
|
_handle->value(value);
|
||||||
|
}
|
||||||
|
// try to handle error as unsigned in case of overflow
|
||||||
|
catch ( const SyntaxException& )
|
||||||
|
{
|
||||||
|
unsigned value = token->asUnsignedInteger();
|
||||||
|
_handle->value(value);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -192,12 +192,42 @@ void JSONTest::testNumberProperty()
|
|||||||
assert(value == 1969);
|
assert(value == 1969);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONTest::testUnsignedNumberProperty()
|
||||||
|
{
|
||||||
|
// 4294967295 == unsigned(-1)
|
||||||
|
std::string json = "{ \"test\" : 4294967295 }";
|
||||||
|
Parser parser;
|
||||||
|
Var result;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DefaultHandler handler;
|
||||||
|
parser.setHandler(&handler);
|
||||||
|
parser.parse(json);
|
||||||
|
result = handler.result();
|
||||||
|
}
|
||||||
|
catch(JSONException& jsone)
|
||||||
|
{
|
||||||
|
std::cout << jsone.message() << std::endl;
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(result.type() == typeid(Object::Ptr));
|
||||||
|
|
||||||
|
Object::Ptr object = result.extract<Object::Ptr>();
|
||||||
|
Var test = object->get("test");
|
||||||
|
assert(test.isInteger());
|
||||||
|
unsigned value = test;
|
||||||
|
assert(value == -1);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
|
|
||||||
|
|
||||||
void JSONTest::testNumber64Property()
|
void JSONTest::testNumber64Property()
|
||||||
{
|
{
|
||||||
std::string json = "{ \"test\" : 5000000000000000 }";
|
std::string json = "{ \"test\" : -5000000000000000 }";
|
||||||
Parser parser;
|
Parser parser;
|
||||||
Var result;
|
Var result;
|
||||||
|
|
||||||
@ -220,10 +250,39 @@ void JSONTest::testNumber64Property()
|
|||||||
Var test = object->get("test");
|
Var test = object->get("test");
|
||||||
assert(test.isInteger());
|
assert(test.isInteger());
|
||||||
Poco::Int64 value = test;
|
Poco::Int64 value = test;
|
||||||
assert(value == 5000000000000000);
|
assert(value == -5000000000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void JSONTest::testUnsignedNumber64Property()
|
||||||
|
{
|
||||||
|
// 18446744073709551615 == UInt64(-1)
|
||||||
|
std::string json = "{ \"test\" : 18446744073709551615 }";
|
||||||
|
Parser parser;
|
||||||
|
Var result;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DefaultHandler handler;
|
||||||
|
parser.setHandler(&handler);
|
||||||
|
parser.parse(json);
|
||||||
|
result = handler.result();
|
||||||
|
}
|
||||||
|
catch(JSONException& jsone)
|
||||||
|
{
|
||||||
|
std::cout << jsone.message() << std::endl;
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(result.type() == typeid(Object::Ptr));
|
||||||
|
|
||||||
|
Object::Ptr object = result.extract<Object::Ptr>();
|
||||||
|
Var test = object->get("test");
|
||||||
|
assert(test.isInteger());
|
||||||
|
Poco::UInt64 value = test;
|
||||||
|
assert(value == -1);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -962,8 +1021,10 @@ CppUnit::Test* JSONTest::suite()
|
|||||||
CppUnit_addTest(pSuite, JSONTest, testTrueProperty);
|
CppUnit_addTest(pSuite, JSONTest, testTrueProperty);
|
||||||
CppUnit_addTest(pSuite, JSONTest, testFalseProperty);
|
CppUnit_addTest(pSuite, JSONTest, testFalseProperty);
|
||||||
CppUnit_addTest(pSuite, JSONTest, testNumberProperty);
|
CppUnit_addTest(pSuite, JSONTest, testNumberProperty);
|
||||||
|
CppUnit_addTest(pSuite, JSONTest, testUnsignedNumberProperty);
|
||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
CppUnit_addTest(pSuite, JSONTest, testNumber64Property);
|
CppUnit_addTest(pSuite, JSONTest, testNumber64Property);
|
||||||
|
CppUnit_addTest(pSuite, JSONTest, testUnsignedNumber64Property);
|
||||||
#endif
|
#endif
|
||||||
CppUnit_addTest(pSuite, JSONTest, testStringProperty);
|
CppUnit_addTest(pSuite, JSONTest, testStringProperty);
|
||||||
CppUnit_addTest(pSuite, JSONTest, testEmptyObject);
|
CppUnit_addTest(pSuite, JSONTest, testEmptyObject);
|
||||||
|
@ -50,8 +50,10 @@ public:
|
|||||||
void testTrueProperty();
|
void testTrueProperty();
|
||||||
void testFalseProperty();
|
void testFalseProperty();
|
||||||
void testNumberProperty();
|
void testNumberProperty();
|
||||||
|
void testUnsignedNumberProperty();
|
||||||
#if defined(POCO_HAVE_INT64)
|
#if defined(POCO_HAVE_INT64)
|
||||||
void testNumber64Property();
|
void testNumber64Property();
|
||||||
|
void testUnsignedNumber64Property();
|
||||||
#endif
|
#endif
|
||||||
void testStringProperty();
|
void testStringProperty();
|
||||||
void testEmptyObject();
|
void testEmptyObject();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user