Skip to content

Commit

Permalink
Fix wrong arguments in callv with const Array
Browse files Browse the repository at this point in the history
  • Loading branch information
Nolkaloid committed Jun 28, 2024
1 parent e052a53 commit b5da867
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 9 deletions.
32 changes: 26 additions & 6 deletions core/object/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,21 +733,41 @@ void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid)
}

Variant Object::callv(const StringName &p_method, const Array &p_args) {
int argcount = p_args.size();
const Variant **argptrs = nullptr;
Variant *args = nullptr;

if (p_args.size() > 0) {
argptrs = (const Variant **)alloca(sizeof(Variant *) * p_args.size());
for (int i = 0; i < p_args.size(); i++) {
argptrs[i] = &p_args[i];
if (argcount > 0) {
argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount);

// Make copies of the arguments if the array is read-only, otherwise the address of p_arguments->read_only will be copied for each.
if (p_args.is_read_only()) {
args = (Variant *)alloca(sizeof(Variant) * argcount);
for (int i = 0; i < argcount; i++) {
memnew_placement(args + i, Variant(p_args[i]));
argptrs[i] = &args[i];
}
} else {
for (int i = 0; i < argcount; i++) {
argptrs[i] = &p_args[i];
}
}
}

Callable::CallError ce;
Variant ret = callp(p_method, argptrs, p_args.size(), ce);
if (ce.error != Callable::CallError::CALL_OK) {
ERR_FAIL_V_MSG(Variant(), "Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + ".");
ERR_PRINT("Error calling method from 'callv': " + Variant::get_call_error_text(this, p_method, argptrs, p_args.size(), ce) + ".");
}
return ret;

// Destroy the copies of the arguments if any.
if (args) {
for (int i = 0; i < argcount; i++) {
args[i].~Variant();
}
}

return (ce.error != Callable::CallError::CALL_OK) ? Variant() : ret;
}

Variant Object::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
Expand Down
27 changes: 24 additions & 3 deletions core/variant/callable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,36 @@ void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_ret
Variant Callable::callv(const Array &p_arguments) const {
int argcount = p_arguments.size();
const Variant **argptrs = nullptr;
if (argcount) {
Variant *args = nullptr;

if (argcount > 0) {
argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount);
for (int i = 0; i < argcount; i++) {
argptrs[i] = &p_arguments[i];

// Make copies of the arguments if the array is read-only, otherwise the address of p_arguments->read_only will be copied for each.
if (p_arguments.is_read_only()) {
args = (Variant *)alloca(sizeof(Variant) * argcount);
for (int i = 0; i < argcount; i++) {
memnew_placement(args + i, Variant(p_arguments[i]));
argptrs[i] = &args[i];
}
} else {
for (int i = 0; i < argcount; i++) {
argptrs[i] = &p_arguments[i];
}
}
}

CallError ce;
Variant ret;
callp(argptrs, argcount, ret, ce);

// Destroy the copies of the arguments if any.
if (args) {
for (int i = 0; i < argcount; i++) {
args[i].~Variant();
}
}

return ret;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
var array_var: Array = ["one", "two", "three", "four"]
const array_const: Array = ["one", "two", "three", "four"]

var array_nested_var: Array = [["one"], ["two"], ["three"], ["four"]]
const array_nested_const: Array = [["one"], ["two"], ["three"], ["four"]]


func test():
assert(array_const.is_read_only() == true)
assert(array_nested_const.is_read_only() == true)

print("TEST Callable::callv")
print_four_variants.callv(array_var)
print_four_variants.callv(array_const)
print_four_variants.callv(array_nested_var)
print_four_variants.callv(array_nested_const)

print("TEST Object::callv")
self.callv("print_four_variants", array_var)
self.callv("print_four_variants", array_const)
self.callv("print_four_variants", array_nested_var)
self.callv("print_four_variants", array_nested_const)


func print_four_variants(v1, v2, v3, v4):
print("%s %s %s %s" % [v1, v2, v3, v4])
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
GDTEST_OK
TEST Callable::callv
one two three four
one two three four
["one"] ["two"] ["three"] ["four"]
["one"] ["two"] ["three"] ["four"]
TEST Object::callv
one two three four
one two three four
["one"] ["two"] ["three"] ["four"]
["one"] ["two"] ["three"] ["four"]

0 comments on commit b5da867

Please sign in to comment.