You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-09 12:50:35 +00:00
Return a correctly typed variant in case of a function error to prevent hard crashes
This commit is contained in:
@@ -502,6 +502,8 @@ private:
|
|||||||
|
|
||||||
List<StackDebug> stack_debug;
|
List<StackDebug> stack_debug;
|
||||||
|
|
||||||
|
Variant _get_default_variant_for_data_type(const GDScriptDataType &p_data_type);
|
||||||
|
|
||||||
_FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, Variant *p_stack, String &r_error) const;
|
_FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, Variant *p_stack, String &r_error) const;
|
||||||
_FORCE_INLINE_ String _get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const;
|
_FORCE_INLINE_ String _get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const;
|
||||||
|
|
||||||
|
|||||||
@@ -123,6 +123,34 @@ static String _get_var_type(const Variant *p_var) {
|
|||||||
}
|
}
|
||||||
#endif // DEBUG_ENABLED
|
#endif // DEBUG_ENABLED
|
||||||
|
|
||||||
|
Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataType &p_data_type) {
|
||||||
|
if (p_data_type.kind == GDScriptDataType::BUILTIN) {
|
||||||
|
if (p_data_type.builtin_type == Variant::ARRAY) {
|
||||||
|
Array array;
|
||||||
|
// Typed array.
|
||||||
|
if (p_data_type.has_container_element_type()) {
|
||||||
|
const GDScriptDataType &element_type = p_data_type.get_container_element_type();
|
||||||
|
array.set_typed(
|
||||||
|
element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT,
|
||||||
|
element_type.native_type,
|
||||||
|
element_type.script_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
} else {
|
||||||
|
Callable::CallError ce;
|
||||||
|
Variant variant;
|
||||||
|
Variant::construct(p_data_type.builtin_type, variant, nullptr, 0, ce);
|
||||||
|
|
||||||
|
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, Variant());
|
||||||
|
|
||||||
|
return variant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
|
||||||
String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const {
|
String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const {
|
||||||
String err_text;
|
String err_text;
|
||||||
|
|
||||||
@@ -428,7 +456,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
OPCODES_TABLE;
|
OPCODES_TABLE;
|
||||||
|
|
||||||
if (!_code_ptr) {
|
if (!_code_ptr) {
|
||||||
return Variant();
|
return _get_default_variant_for_data_type(return_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
r_err.error = Callable::CallError::CALL_OK;
|
r_err.error = Callable::CallError::CALL_OK;
|
||||||
@@ -467,11 +495,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
|
r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||||
r_err.argument = _argument_count;
|
r_err.argument = _argument_count;
|
||||||
|
|
||||||
return Variant();
|
return _get_default_variant_for_data_type(return_type);
|
||||||
} else if (p_argcount < _argument_count - _default_arg_count) {
|
} else if (p_argcount < _argument_count - _default_arg_count) {
|
||||||
r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
|
r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||||
r_err.argument = _argument_count - _default_arg_count;
|
r_err.argument = _argument_count - _default_arg_count;
|
||||||
return Variant();
|
return _get_default_variant_for_data_type(return_type);
|
||||||
} else {
|
} else {
|
||||||
defarg = _argument_count - p_argcount;
|
defarg = _argument_count - p_argcount;
|
||||||
}
|
}
|
||||||
@@ -498,7 +526,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
|
r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
|
||||||
r_err.argument = i;
|
r_err.argument = i;
|
||||||
r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
|
r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
|
||||||
return Variant();
|
return _get_default_variant_for_data_type(return_type);
|
||||||
}
|
}
|
||||||
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
|
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
|
||||||
Variant arg;
|
Variant arg;
|
||||||
@@ -3324,6 +3352,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// Get a default return type in case of failure
|
||||||
|
retvalue = _get_default_variant_for_data_type(return_type);
|
||||||
|
|
||||||
OPCODE_OUT;
|
OPCODE_OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user