mirror of https://github.com/godotengine/godot
Merge pull request #71228 from vnen/gdscript-fix-nil-address-crash
GDScript: Fix temp values being written without proper clear
This commit is contained in:
commit
11449e1079
|
|
@ -920,11 +920,17 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres
|
|||
append(index);
|
||||
}
|
||||
|
||||
GDScriptCodeGenerator::Address GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target) {
|
||||
GDScriptCodeGenerator::Address GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target, Variant::Type p_type) {
|
||||
if (p_target.mode == Address::NIL) {
|
||||
uint32_t addr = add_temporary(p_target.type);
|
||||
GDScriptDataType type;
|
||||
if (p_type != Variant::NIL) {
|
||||
type.has_type = true;
|
||||
type.kind = GDScriptDataType::BUILTIN;
|
||||
type.builtin_type = p_type;
|
||||
}
|
||||
uint32_t addr = add_temporary(type);
|
||||
pop_temporary();
|
||||
return Address(Address::TEMPORARY, addr, p_target.type);
|
||||
return Address(Address::TEMPORARY, addr, type);
|
||||
} else {
|
||||
return p_target;
|
||||
}
|
||||
|
|
@ -989,11 +995,17 @@ void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, cons
|
|||
}
|
||||
|
||||
if (is_validated) {
|
||||
Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL;
|
||||
Address target = get_call_target(p_target, result_type);
|
||||
Variant::Type temp_type = temporaries[target.address].type;
|
||||
if (result_type != temp_type) {
|
||||
write_type_adjust(target, result_type);
|
||||
}
|
||||
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY_VALIDATED, 1 + p_arguments.size());
|
||||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
append(p_arguments[i]);
|
||||
}
|
||||
append(get_call_target(p_target));
|
||||
append(target);
|
||||
append(p_arguments.size());
|
||||
append(Variant::get_validated_utility_function(p_function));
|
||||
} else {
|
||||
|
|
@ -1007,7 +1019,7 @@ void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, cons
|
|||
}
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) {
|
||||
void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, bool p_is_static, const Vector<Address> &p_arguments) {
|
||||
bool is_validated = false;
|
||||
|
||||
// Check if all types are correct.
|
||||
|
|
@ -1027,16 +1039,26 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
|
|||
|
||||
if (!is_validated) {
|
||||
// Perform regular call.
|
||||
write_call(p_target, p_base, p_method, p_arguments);
|
||||
if (p_is_static) {
|
||||
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_STATIC, p_arguments.size() + 1);
|
||||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
append(p_arguments[i]);
|
||||
}
|
||||
append(get_call_target(p_target));
|
||||
append(p_type);
|
||||
append(p_method);
|
||||
append(p_arguments.size());
|
||||
} else {
|
||||
write_call(p_target, p_base, p_method, p_arguments);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_target.mode == Address::TEMPORARY) {
|
||||
Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
|
||||
Variant::Type temp_type = temporaries[p_target.address].type;
|
||||
if (result_type != temp_type) {
|
||||
write_type_adjust(p_target, result_type);
|
||||
}
|
||||
Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
|
||||
Address target = get_call_target(p_target, result_type);
|
||||
Variant::Type temp_type = temporaries[target.address].type;
|
||||
if (result_type != temp_type) {
|
||||
write_type_adjust(target, result_type);
|
||||
}
|
||||
|
||||
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
|
||||
|
|
@ -1045,59 +1067,17 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
|
|||
append(p_arguments[i]);
|
||||
}
|
||||
append(p_base);
|
||||
append(get_call_target(p_target));
|
||||
append(target);
|
||||
append(p_arguments.size());
|
||||
append(Variant::get_validated_builtin_method(p_type, p_method));
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) {
|
||||
write_call_builtin_type(p_target, p_base, p_type, p_method, false, p_arguments);
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) {
|
||||
bool is_validated = false;
|
||||
|
||||
// Check if all types are correct.
|
||||
if (Variant::is_builtin_method_vararg(p_type, p_method)) {
|
||||
is_validated = true; // Vararg works fine with any argument, since they can be any type.
|
||||
} else if (p_arguments.size() == Variant::get_builtin_method_argument_count(p_type, p_method)) {
|
||||
bool all_types_exact = true;
|
||||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_builtin_method_argument_type(p_type, p_method, i))) {
|
||||
all_types_exact = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
is_validated = all_types_exact;
|
||||
}
|
||||
|
||||
if (!is_validated) {
|
||||
// Perform regular call.
|
||||
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_STATIC, p_arguments.size() + 1);
|
||||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
append(p_arguments[i]);
|
||||
}
|
||||
append(get_call_target(p_target));
|
||||
append(p_type);
|
||||
append(p_method);
|
||||
append(p_arguments.size());
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_target.mode == Address::TEMPORARY) {
|
||||
Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
|
||||
Variant::Type temp_type = temporaries[p_target.address].type;
|
||||
if (result_type != temp_type) {
|
||||
write_type_adjust(p_target, result_type);
|
||||
}
|
||||
}
|
||||
|
||||
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
|
||||
|
||||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
append(p_arguments[i]);
|
||||
}
|
||||
append(Address()); // No base since it's static.
|
||||
append(get_call_target(p_target));
|
||||
append(p_arguments.size());
|
||||
append(Variant::get_validated_builtin_method(p_type, p_method));
|
||||
write_call_builtin_type(p_target, Address(), p_type, p_method, true, p_arguments);
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) {
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
Address get_call_target(const Address &p_target);
|
||||
Address get_call_target(const Address &p_target, Variant::Type p_type = Variant::NIL);
|
||||
|
||||
int address_of(const Address &p_address) {
|
||||
switch (p_address.mode) {
|
||||
|
|
@ -469,6 +469,7 @@ public:
|
|||
virtual void write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
||||
virtual void write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) override;
|
||||
virtual void write_call_gdscript_utility(const Address &p_target, GDScriptUtilityFunctions::FunctionPtr p_function, const Vector<Address> &p_arguments) override;
|
||||
void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, bool p_is_static, const Vector<Address> &p_arguments);
|
||||
virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override;
|
||||
virtual void write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override;
|
||||
virtual void write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) override;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# https://github.com/godotengine/godot/issues/71177
|
||||
|
||||
func test():
|
||||
builtin_method()
|
||||
builtin_method_static()
|
||||
print("done")
|
||||
|
||||
func builtin_method():
|
||||
var pba := PackedByteArray()
|
||||
@warning_ignore(return_value_discarded)
|
||||
pba.resize(1) # Built-in validated.
|
||||
|
||||
|
||||
func builtin_method_static():
|
||||
var _pba := PackedByteArray()
|
||||
@warning_ignore(return_value_discarded)
|
||||
Vector2.from_angle(PI) # Static built-in validated.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
GDTEST_OK
|
||||
done
|
||||
Loading…
Reference in New Issue