From 3ca7b4ee451cd67db1148b07e45f717506be7730 Mon Sep 17 00:00:00 2001 From: Bojidar Marinov Date: Tue, 3 Sep 2019 10:39:04 +0300 Subject: [PATCH] Fix uninitialized arrays and dictionaries retaining value Fixes #28978 --- modules/gdscript/gdscript_parser.cpp | 83 ++++++++++++++++------------ modules/gdscript/gdscript_parser.h | 1 + 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index e96bf0238a5..db812ecb22c 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2846,15 +2846,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) { assigned = subexpr; } else { - ConstantNode *c = alloc_node(); - if (lv->datatype.has_type && lv->datatype.kind == DataType::BUILTIN) { - Variant::CallError err; - c->value = Variant::construct(lv->datatype.builtin_type, NULL, 0, err); - } else { - c->value = Variant(); - } - c->line = var_line; - assigned = c; + assigned = _get_default_value_for_type(lv->datatype, var_line); } lv->assign = assigned; //must be added later, to avoid self-referencing. @@ -4839,35 +4831,29 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - Variant::Type initial_type = member.data_type.has_type ? member.data_type.builtin_type : member._export.type; + Node *expr; - if (initial_type != Variant::NIL && initial_type != Variant::OBJECT) { - IdentifierNode *id = alloc_node(); - id->name = member.identifier; - - Node *expr; - - // Make sure arrays and dictionaries are not shared - if (initial_type == Variant::ARRAY) { - expr = alloc_node(); - } else if (initial_type == Variant::DICTIONARY) { - expr = alloc_node(); - } else { - ConstantNode *cn = alloc_node(); - Variant::CallError ce2; - cn->value = Variant::construct(initial_type, NULL, 0, ce2); - expr = cn; - } - - OperatorNode *op = alloc_node(); - op->op = OperatorNode::OP_INIT_ASSIGN; - op->arguments.push_back(id); - op->arguments.push_back(expr); - - p_class->initializer->statements.push_back(op); - - member.initial_assignment = op; + if (member.data_type.has_type) { + expr = _get_default_value_for_type(member.data_type); + } else { + DataType exported_type; + exported_type.has_type = true; + exported_type.kind = DataType::BUILTIN; + exported_type.builtin_type = member._export.type; + expr = _get_default_value_for_type(exported_type); } + + IdentifierNode *id = alloc_node(); + id->name = member.identifier; + + OperatorNode *op = alloc_node(); + op->op = OperatorNode::OP_INIT_ASSIGN; + op->arguments.push_back(id); + op->arguments.push_back(expr); + + p_class->initializer->statements.push_back(op); + + member.initial_assignment = op; } if (autoexport && member.data_type.has_type) { @@ -6140,6 +6126,31 @@ bool GDScriptParser::_is_type_compatible(const DataType &p_container, const Data return false; } +GDScriptParser::Node *GDScriptParser::_get_default_value_for_type(const DataType &p_type, int p_line) { + Node *result; + + if (p_type.has_type && p_type.kind == DataType::BUILTIN && p_type.builtin_type != Variant::NIL && p_type.builtin_type != Variant::OBJECT) { + if (p_type.builtin_type == Variant::ARRAY) { + result = alloc_node(); + } else if (p_type.builtin_type == Variant::DICTIONARY) { + result = alloc_node(); + } else { + ConstantNode *c = alloc_node(); + Variant::CallError err; + c->value = Variant::construct(p_type.builtin_type, NULL, 0, err); + result = c; + } + } else { + ConstantNode *c = alloc_node(); + c->value = Variant(); + result = c; + } + + result->line = p_line; + + return result; +} + GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) { #ifdef DEBUG_ENABLED if (p_node->get_datatype().has_type && p_node->type != Node::TYPE_ARRAY && p_node->type != Node::TYPE_DICTIONARY) { diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 72aa819a8cd..8594c96fcd7 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -610,6 +610,7 @@ private: bool _get_function_signature(DataType &p_base_type, const StringName &p_function, DataType &r_return_type, List &r_arg_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) const; bool _get_member_type(const DataType &p_base_type, const StringName &p_member, DataType &r_member_type) const; bool _is_type_compatible(const DataType &p_container, const DataType &p_expression, bool p_allow_implicit_conversion = false) const; + Node *_get_default_value_for_type(const DataType &p_type, int p_line = -1); DataType _reduce_node_type(Node *p_node); DataType _reduce_function_call_type(const OperatorNode *p_call);