Check string accesses during JSON parsing

This commit is contained in:
Jason Turner 2017-07-19 10:47:17 -06:00
parent cfb2e663d3
commit d8da295e40
2 changed files with 24 additions and 20 deletions

View File

@ -463,7 +463,7 @@ struct JSONParser {
} }
static void consume_ws( const std::string &str, size_t &offset ) { static void consume_ws( const std::string &str, size_t &offset ) {
while( isspace( str[offset] ) && offset <= str.size() ) { ++offset; } while( isspace( str.at(offset) ) && offset <= str.size() ) { ++offset; }
} }
static JSON parse_object( const std::string &str, size_t &offset ) { static JSON parse_object( const std::string &str, size_t &offset ) {
@ -471,29 +471,29 @@ struct JSONParser {
++offset; ++offset;
consume_ws( str, offset ); consume_ws( str, offset );
if( str[offset] == '}' ) { if( str.at(offset) == '}' ) {
++offset; return Object; ++offset; return Object;
} }
for (;offset<str.size();) { for (;offset<str.size();) {
JSON Key = parse_next( str, offset ); JSON Key = parse_next( str, offset );
consume_ws( str, offset ); consume_ws( str, offset );
if( str[offset] != ':' ) { if( str.at(offset) != ':' ) {
throw std::runtime_error(std::string("JSON ERROR: Object: Expected colon, found '") + str[offset] + "'\n"); throw std::runtime_error(std::string("JSON ERROR: Object: Expected colon, found '") + str.at(offset) + "'\n");
} }
consume_ws( str, ++offset ); consume_ws( str, ++offset );
JSON Value = parse_next( str, offset ); JSON Value = parse_next( str, offset );
Object[Key.to_string()] = Value; Object[Key.to_string()] = Value;
consume_ws( str, offset ); consume_ws( str, offset );
if( str[offset] == ',' ) { if( str.at(offset) == ',' ) {
++offset; continue; ++offset; continue;
} }
else if( str[offset] == '}' ) { else if( str.at(offset) == '}' ) {
++offset; break; ++offset; break;
} }
else { else {
throw std::runtime_error(std::string("JSON ERROR: Object: Expected comma, found '") + str[offset] + "'\n"); throw std::runtime_error(std::string("JSON ERROR: Object: Expected comma, found '") + str.at(offset) + "'\n");
} }
} }
@ -506,7 +506,7 @@ struct JSONParser {
++offset; ++offset;
consume_ws( str, offset ); consume_ws( str, offset );
if( str[offset] == ']' ) { if( str.at(offset) == ']' ) {
++offset; return Array; ++offset; return Array;
} }
@ -514,14 +514,14 @@ struct JSONParser {
Array[index++] = parse_next( str, offset ); Array[index++] = parse_next( str, offset );
consume_ws( str, offset ); consume_ws( str, offset );
if( str[offset] == ',' ) { if( str.at(offset) == ',' ) {
++offset; continue; ++offset; continue;
} }
else if( str[offset] == ']' ) { else if( str.at(offset) == ']' ) {
++offset; break; ++offset; break;
} }
else { else {
throw std::runtime_error(std::string("JSON ERROR: Array: Expected ',' or ']', found '") + str[offset] + "'\n"); throw std::runtime_error(std::string("JSON ERROR: Array: Expected ',' or ']', found '") + str.at(offset) + "'\n");
} }
} }
@ -530,9 +530,9 @@ struct JSONParser {
static JSON parse_string( const std::string &str, size_t &offset ) { static JSON parse_string( const std::string &str, size_t &offset ) {
std::string val; std::string val;
for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) { for( char c = str.at(++offset); c != '\"' ; c = str.at(++offset) ) {
if( c == '\\' ) { if( c == '\\' ) {
switch( str[ ++offset ] ) { switch( str.at(++offset) ) {
case '\"': val += '\"'; break; case '\"': val += '\"'; break;
case '\\': val += '\\'; break; case '\\': val += '\\'; break;
case '/' : val += '/' ; break; case '/' : val += '/' ; break;
@ -544,7 +544,7 @@ struct JSONParser {
case 'u' : { case 'u' : {
val += "\\u" ; val += "\\u" ;
for( size_t i = 1; i <= 4; ++i ) { for( size_t i = 1; i <= 4; ++i ) {
c = str[offset+i]; c = str.at(offset+i);
if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) { if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) {
val += c; val += c;
} else { } else {
@ -569,12 +569,12 @@ struct JSONParser {
bool isDouble = false; bool isDouble = false;
bool isNegative = false; bool isNegative = false;
long exp = 0; long exp = 0;
if( offset < str.size() && str[offset] == '-' ) { if( offset < str.size() && str.at(offset) == '-' ) {
isNegative = true; isNegative = true;
++offset; ++offset;
} }
for (; offset < str.size() ;) { for (; offset < str.size() ;) {
c = str[offset++]; c = str.at(offset++);
if( c >= '0' && c <= '9' ) { if( c >= '0' && c <= '9' ) {
val += c; val += c;
} else if( c == '.' && !isDouble ) { } else if( c == '.' && !isDouble ) {
@ -585,7 +585,7 @@ struct JSONParser {
} }
} }
if( offset < str.size() && (c == 'E' || c == 'e' )) { if( offset < str.size() && (c == 'E' || c == 'e' )) {
c = str[ offset++ ]; c = str.at(offset++);
if( c == '-' ) { if( c == '-' ) {
exp_str += '-'; exp_str += '-';
} else if( c == '+' ) { } else if( c == '+' ) {
@ -595,7 +595,7 @@ struct JSONParser {
} }
for (; offset < str.size() ;) { for (; offset < str.size() ;) {
c = str[ offset++ ]; c = str.at(offset++);
if( c >= '0' && c <= '9' ) { if( c >= '0' && c <= '9' ) {
exp_str += c; exp_str += c;
} else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) { } else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
@ -646,7 +646,7 @@ struct JSONParser {
static JSON parse_next( const std::string &str, size_t &offset ) { static JSON parse_next( const std::string &str, size_t &offset ) {
char value; char value;
consume_ws( str, offset ); consume_ws( str, offset );
value = str[offset]; value = str.at(offset);
switch( value ) { switch( value ) {
case '[' : return parse_array( str, offset ); case '[' : return parse_array( str, offset );
case '{' : return parse_object( str, offset ); case '{' : return parse_object( str, offset );

View File

@ -63,7 +63,11 @@ namespace chaiscript
static Boxed_Value from_json(const std::string &t_json) static Boxed_Value from_json(const std::string &t_json)
{ {
try {
return from_json( json::JSON::Load(t_json) ); return from_json( json::JSON::Load(t_json) );
} catch (...) {
throw std::runtime_error("Unparsed JSON input");
}
} }
static std::string to_json(const Boxed_Value &t_bv) static std::string to_json(const Boxed_Value &t_bv)