diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/gdscript/gdscript.cpp | 2 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_analyzer.cpp | 24 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_function.h | 2 | ||||
| -rw-r--r-- | modules/gdscript/gdscript_vm.cpp | 32 | ||||
| -rw-r--r-- | modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd | 4 |
5 files changed, 53 insertions, 11 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index fe79f37454..00f8d2817a 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -2563,7 +2563,7 @@ GDScriptLanguage::GDScriptLanguage() { script_frame_time = 0; _debug_call_stack_pos = 0; - int dmcs = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "1024,4096,1,or_greater"), 1024); + int dmcs = GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/settings/gdscript/max_call_stack", PROPERTY_HINT_RANGE, "512," + itos(GDScriptFunction::MAX_CALL_DEPTH - 1) + ",1"), 1024); if (EngineDebugger::is_active()) { //debugging enabled! diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index d0525be853..c8dfdbdd68 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -4252,18 +4252,22 @@ Variant GDScriptAnalyzer::make_subscript_reduced_value(GDScriptParser::Subscript Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) { Array array; - Ref<Script> script_type = p_element_datatype.script_type; - if (p_element_datatype.kind == GDScriptParser::DataType::CLASS && script_type.is_null()) { - Error err = OK; - Ref<GDScript> scr = GDScriptCache::get_shallow_script(p_element_datatype.script_path, err); - if (err) { - push_error(vformat(R"(Error while getting cache for script "%s".)", p_element_datatype.script_path), p_source_node); - return array; + if (p_element_datatype.builtin_type == Variant::OBJECT) { + Ref<Script> script_type = p_element_datatype.script_type; + if (p_element_datatype.kind == GDScriptParser::DataType::CLASS && script_type.is_null()) { + Error err = OK; + Ref<GDScript> scr = GDScriptCache::get_shallow_script(p_element_datatype.script_path, err); + if (err) { + push_error(vformat(R"(Error while getting cache for script "%s".)", p_element_datatype.script_path), p_source_node); + return array; + } + script_type.reference_ptr(scr->find_class(p_element_datatype.class_type->fqcn)); } - script_type.reference_ptr(scr->find_class(p_element_datatype.class_type->fqcn)); - } - array.set_typed(p_element_datatype.builtin_type, p_element_datatype.native_type, script_type); + array.set_typed(p_element_datatype.builtin_type, p_element_datatype.native_type, script_type); + } else { + array.set_typed(p_element_datatype.builtin_type, StringName(), Variant()); + } return array; } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index f45c1f9577..2624fb8dd9 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -544,6 +544,8 @@ private: #endif public: + static constexpr int MAX_CALL_DEPTH = 2048; // Limit to try to avoid crash because of a stack overflow. + struct CallState { GDScript *script = nullptr; GDScriptInstance *instance = nullptr; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 4db41c4dfa..fd8875d8b1 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -459,6 +459,33 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a r_err.error = Callable::CallError::CALL_OK; + static thread_local int call_depth = 0; + if (unlikely(++call_depth > MAX_CALL_DEPTH)) { + call_depth--; +#ifdef DEBUG_ENABLED + String err_file; + if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && !p_instance->script->path.is_empty()) { + err_file = p_instance->script->path; + } else if (_script) { + err_file = _script->path; + } + if (err_file.is_empty()) { + err_file = "<built-in>"; + } + String err_func = name; + if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && !p_instance->script->name.is_empty()) { + err_func = p_instance->script->name + "." + err_func; + } + int err_line = _initial_line; + const char *err_text = "Stack overflow. Check for infinite recursion in your script."; + if (!GDScriptLanguage::get_singleton()->debug_break(err_text, false)) { + // Debugger break did not happen. + _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text, false, ERR_HANDLER_SCRIPT); + } +#endif + return _get_default_variant_for_data_type(return_type); + } + Variant retvalue; Variant *stack = nullptr; Variant **instruction_args = nullptr; @@ -493,10 +520,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; r_err.argument = _argument_count; + call_depth--; return _get_default_variant_for_data_type(return_type); } else if (p_argcount < _argument_count - _default_arg_count) { r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_err.argument = _argument_count - _default_arg_count; + call_depth--; return _get_default_variant_for_data_type(return_type); } else { defarg = _argument_count - p_argcount; @@ -524,6 +553,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_err.argument = i; r_err.expected = argument_types[i].builtin_type; + call_depth--; return _get_default_variant_for_data_type(return_type); } if (argument_types[i].kind == GDScriptDataType::BUILTIN) { @@ -3603,5 +3633,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a stack[i].~Variant(); } + call_depth--; + return retvalue; } diff --git a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd index 7416ecd87a..26542a9e2f 100644 --- a/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd +++ b/modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd @@ -201,6 +201,10 @@ func test(): assert(str(typed_enums) == '[391]') assert(typed_enums.get_typed_builtin() == TYPE_INT) + const const_enums: Array[E] = [] + assert(const_enums.get_typed_builtin() == TYPE_INT) + assert(const_enums.get_typed_class_name() == &'') + var a := A.new() var typed_natives: Array[RefCounted] = [a] |