--- parser3/src/classes/json.C 2015/07/22 18:29:09 1.35 +++ parser3/src/classes/json.C 2015/10/26 01:21:54 1.40 @@ -1,7 +1,7 @@ /** @file Parser: @b json parser class. - Copyright (c) 2000-2012 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2000-2015 Art. Lebedev Studio (http://www.artlebedev.com) */ #include "classes.h" @@ -18,7 +18,7 @@ #include "pa_vxdoc.h" #endif -volatile const char * IDENT_JSON_C="$Id: json.C,v 1.35 2015/07/22 18:29:09 moko Exp $"; +volatile const char * IDENT_JSON_C="$Id: json.C,v 1.40 2015/10/26 01:21:54 moko Exp $"; // class @@ -97,7 +97,7 @@ String* json_string(Json *json, const ch String::C result = json->charset !=NULL ? Charset::transcode(String::C(value, length), UTF8_charset, *json->charset) : String::C(pa_strdup(value, length), length); - return new String(result.str, json->taint, result.length); + return new String(result, json->taint); } static Value *json_hook(Request &r, Junction *hook, String* key, Value* value){ @@ -343,6 +343,13 @@ static void _parse(Request& r, MethodPar if(int result = json_parser_init(&parser, &config, (json_parser_callback)&json_callback, &json)) throw Exception("json.parse", 0, "%s", json_error_message(result)); + if(!*json_cstr) + throw Exception("json.parse", 0, "empty string is not valid json"); + + const char *first_quote=strchr(json_cstr,'"'); + if(first_quote && first_quote>json_cstr && *(--first_quote) == '\\') + json_exception_with_source(r, "illegal quote escape, json may be tainted", json_cstr, first_quote-json_cstr); + uint32_t processed; if(int result = json_parser_string(&parser, json_cstr, strlen(json_cstr), &processed)) json_exception_with_source(r, json_error_message(result), json_cstr, processed); @@ -383,8 +390,8 @@ public: const String& value_json_string(String::Body key, Value& v, Json_options& options); -const String* Json_options::hash_json_string(HashStringValue &hash) { - if(!hash.count()) +const String* Json_options::hash_json_string(HashStringValue *hash) { + if(!hash || !hash->count()) return new String("{}", String::L_AS_IS); Json_string_recoursion go_down(*this); @@ -395,7 +402,7 @@ const String* Json_options::hash_json_st String *delim=NULL; indent=get_indent(json_string_recoursion); - for(HashStringValue::Iterator i(hash); i; i.next() ){ + for(HashStringValue::Iterator i(*hash); i; i.next() ){ if (delim){ result << *delim; } else { @@ -409,7 +416,7 @@ const String* Json_options::hash_json_st } else { bool need_delim=false; - for(HashStringValue::Iterator i(hash); i; i.next() ){ + for(HashStringValue::Iterator i(*hash); i; i.next() ){ result << (need_delim ? ",\n\"" : "\""); result << String(i.key(), String::L_JSON) << "\":" << value_json_string(i.key(), *i.value(), *this); need_delim=true; @@ -470,7 +477,7 @@ static void _string(Request& r, MethodPa } else if(key == "date" && value->is_string()){ const String& svalue=value->as_string(); if(!json.set_date_format(svalue)) - throw Exception(PARSER_RUNTIME, &svalue, "must be 'sql-string', 'gmt-string' or 'unix-timestamp'"); + throw Exception(PARSER_RUNTIME, &svalue, "must be 'sql-string', 'gmt-string', 'iso-string' or 'unix-timestamp'"); valid_options++; } else if(key == "indent"){ if(value->is_string()){