From 561c5bc981ead1fd8f38e5949696382691ea2c2a Mon Sep 17 00:00:00 2001 From: Glen Fraser Date: Tue, 14 Mar 2017 12:01:51 +0100 Subject: [PATCH 1/2] Handle negative numbers in JSONParse::parse_number - fix issue #334, where negative numbers loaded from JSON were being parsed as 0. - add unit tests to cover these cases. --- include/chaiscript/utility/json.hpp | 11 +++++++---- unittests/json_3.chai | 1 + unittests/json_4.chai | 1 + unittests/json_9.chai | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 96decc0..6fe2e58 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -567,10 +567,13 @@ struct JSONParser { std::string val, exp_str; char c = '\0'; bool isDouble = false; + bool isNegative = false; long exp = 0; for (; offset < str.size() ;) { c = str[offset++]; - if( (c == '-') || (c >= '0' && c <= '9') ) { + if( c == '-' ) { + isNegative = true; + } else if( c >= '0' && c <= '9' ) { val += c; } else if( c == '.' ) { val += c; @@ -608,12 +611,12 @@ struct JSONParser { --offset; if( isDouble ) { - return JSON(chaiscript::parse_num( val ) * std::pow( 10, exp )); + return JSON((isNegative?-1:1) * chaiscript::parse_num( val ) * std::pow( 10, exp )); } else { if( !exp_str.empty() ) { - return JSON(static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); + return JSON((isNegative?-1:1) * static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); } else { - return JSON(chaiscript::parse_num( val )); + return JSON((isNegative?-1:1) * chaiscript::parse_num( val )); } } } diff --git a/unittests/json_3.chai b/unittests/json_3.chai index d3f222e..11ce7dc 100644 --- a/unittests/json_3.chai +++ b/unittests/json_3.chai @@ -1 +1,2 @@ assert_equal(from_json("100"), 100) +assert_equal(from_json("-100"), -100) diff --git a/unittests/json_4.chai b/unittests/json_4.chai index 22d388c..34ecfa9 100644 --- a/unittests/json_4.chai +++ b/unittests/json_4.chai @@ -1 +1,2 @@ assert_equal(from_json("1.234"), 1.234) +assert_equal(from_json("-1.234"), -1.234) diff --git a/unittests/json_9.chai b/unittests/json_9.chai index 1512738..d8c6423 100644 --- a/unittests/json_9.chai +++ b/unittests/json_9.chai @@ -1,2 +1,2 @@ -assert_equal(from_json("[1,2,3]"), [1,2,3]) +assert_equal(from_json("[1,-2,3]"), [1,-2,3]) From 491b95099dba0aae2c95d373aea6fc99a77ce3be Mon Sep 17 00:00:00 2001 From: Glen Fraser Date: Tue, 14 Mar 2017 13:01:09 +0100 Subject: [PATCH 2/2] In JSONParser::parse_number(), only allow a single '-' at start - also, don't allow multiple '.' decimal points. Add unit tests to cover these cases. --- include/chaiscript/utility/json.hpp | 10 ++++++---- unittests/json_4.chai | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 6fe2e58..676b469 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -569,13 +569,15 @@ struct JSONParser { bool isDouble = false; bool isNegative = false; long exp = 0; + if( offset < str.size() && str[offset] == '-' ) { + isNegative = true; + ++offset; + } for (; offset < str.size() ;) { c = str[offset++]; - if( c == '-' ) { - isNegative = true; - } else if( c >= '0' && c <= '9' ) { + if( c >= '0' && c <= '9' ) { val += c; - } else if( c == '.' ) { + } else if( c == '.' && !isDouble ) { val += c; isDouble = true; } else { diff --git a/unittests/json_4.chai b/unittests/json_4.chai index 34ecfa9..ae07024 100644 --- a/unittests/json_4.chai +++ b/unittests/json_4.chai @@ -1,2 +1,22 @@ assert_equal(from_json("1.234"), 1.234) assert_equal(from_json("-1.234"), -1.234) + +auto caught = false; +try { + from_json("-1-5.3"); +} +catch(e) { + assert_equal("JSON ERROR: Number: unexpected character '-'", e.what()); + caught = true; +} +assert_equal(caught, true); + +caught = false; +try { + from_json("-15.3.2"); +} +catch(e) { + assert_equal("JSON ERROR: Number: unexpected character '.'", e.what()); + caught = true; +} +assert_equal(caught, true);