mirror of
https://github.com/godotengine/godot.git
synced 2025-02-18 16:50:48 +00:00
GDScript: Add limit to call depth
The hard limit is set at 2048 depth which seems sensible between legitimate recursive calls while still avoiding a crash because of a stack overflow in most of the cases. Note that it is still possible to reach the stack limit and get an overflow before reaching a call depth. This is intended as a half-way measure to stop crashing in most cases, since there's no reliable nor portable way to check the amount of stack memory left.
This commit is contained in:
parent
a05670c617
commit
34f0a2ca46
@ -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!
|
||||
|
@ -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;
|
||||
|
@ -456,6 +456,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;
|
||||
@ -490,10 +517,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;
|
||||
@ -521,6 +550,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) {
|
||||
@ -3570,5 +3600,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||
stack[i].~Variant();
|
||||
}
|
||||
|
||||
call_depth--;
|
||||
|
||||
return retvalue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user