summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gdscript.cpp2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp24
-rw-r--r--modules/gdscript/gdscript_function.h2
-rw-r--r--modules/gdscript/gdscript_vm.cpp32
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/typed_array_usage.gd4
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]