From de3b1c3fca9907afbfaa57f98a38d07e4cadca0d Mon Sep 17 00:00:00 2001 From: RedMser Date: Mon, 19 Sep 2022 18:10:23 +0200 Subject: Add recursion depth check to JSON stringify/parse --- core/io/json.cpp | 23 +++++++++++++++-------- core/io/json.h | 6 +++--- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'core/io') diff --git a/core/io/json.cpp b/core/io/json.cpp index a685fcb718..7e267d35d4 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -56,6 +56,8 @@ String JSON::_make_indent(const String &p_indent, int p_size) { } String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, HashSet &p_markers, bool p_full_precision) { + ERR_FAIL_COND_V_MSG(p_cur_indent > Variant::MAX_RECURSION_DEPTH, "...", "JSON structure is too deep. Bailing."); + String colon = ":"; String end_statement = ""; @@ -357,17 +359,22 @@ Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_to return ERR_PARSE_ERROR; } -Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) { +Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str) { + if (p_depth > Variant::MAX_RECURSION_DEPTH) { + r_err_str = "JSON structure is too deep. Bailing."; + return ERR_OUT_OF_MEMORY; + } + if (token.type == TK_CURLY_BRACKET_OPEN) { Dictionary d; - Error err = _parse_object(d, p_str, index, p_len, line, r_err_str); + Error err = _parse_object(d, p_str, index, p_len, line, p_depth + 1, r_err_str); if (err) { return err; } value = d; } else if (token.type == TK_BRACKET_OPEN) { Array a; - Error err = _parse_array(a, p_str, index, p_len, line, r_err_str); + Error err = _parse_array(a, p_str, index, p_len, line, p_depth + 1, r_err_str); if (err) { return err; } @@ -396,7 +403,7 @@ Error JSON::_parse_value(Variant &value, Token &token, const char32_t *p_str, in return OK; } -Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) { +Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str) { Token token; bool need_comma = false; @@ -421,7 +428,7 @@ Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_ } Variant v; - err = _parse_value(v, token, p_str, index, p_len, line, r_err_str); + err = _parse_value(v, token, p_str, index, p_len, line, p_depth, r_err_str); if (err) { return err; } @@ -434,7 +441,7 @@ Error JSON::_parse_array(Array &array, const char32_t *p_str, int &index, int p_ return ERR_PARSE_ERROR; } -Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str) { +Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str) { bool at_key = true; String key; Token token; @@ -483,7 +490,7 @@ Error JSON::_parse_object(Dictionary &object, const char32_t *p_str, int &index, } Variant v; - err = _parse_value(v, token, p_str, index, p_len, line, r_err_str); + err = _parse_value(v, token, p_str, index, p_len, line, p_depth, r_err_str); if (err) { return err; } @@ -514,7 +521,7 @@ Error JSON::_parse_string(const String &p_json, Variant &r_ret, String &r_err_st return err; } - err = _parse_value(r_ret, token, str, idx, len, r_err_line, r_err_str); + err = _parse_value(r_ret, token, str, idx, len, r_err_line, 0, r_err_str); // Check if EOF is reached // or it's a type of the next token. diff --git a/core/io/json.h b/core/io/json.h index 208d4ad625..829a5f922b 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -74,9 +74,9 @@ class JSON : public RefCounted { static String _make_indent(const String &p_indent, int p_size); static String _stringify(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, HashSet &p_markers, bool p_full_precision = false); static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str); - static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); - static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); - static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str); + static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str); + static Error _parse_array(Array &array, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str); + static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, int p_depth, String &r_err_str); static Error _parse_string(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line); protected: -- cgit v1.2.3