-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix call with wrong arguments in Callable.callv() when passing a readonly (const) Array #93636
base: master
Are you sure you want to change the base?
Conversation
e64f92a
to
c166647
Compare
This would really benefit from having a test added under |
As this is not GDScript specific, shouldn't it be a unit test in |
We do many of these tests there
My bad missed some details, but I think the script side tests works best to fix this |
Given some of the details here I think I have a potential alternative solution that might be better, I'll look at it along with my other changes in: But if you want to try it out I'll drop the alternative here, it probably would be faster and easier avoiding a full duplication with: Variant *args = nullptr;
const Variant **argptrs = nullptr;
if (argcount) {
argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount);
// Copy the arguments if read-only, otherwise the address of p_arguments->read_only will be copied.
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);
if (args) {
for (int i = 0; i < argcount; i++) {
args[i].~Variant();
}
}
return ret; Edit: Tested and it works well, a bit more code but avoids unnecessary duplication |
Having a second buffer allocated for a copy of the elements is what I have done initially, but I chose to use I'm not sure that the call to |
I'm not sure, that's a good point and it might not matter, but i don't think the code is significantly less readable and it avoids potential weirdness |
I did a quick check, and indeed the duplication is done using CoW. If it were up to me I'd keep the |
You decide, both are fine by me, and let's see what the core team says |
c166647
to
606ec2e
Compare
A few thoughts:
|
I think it might be difficult to handle the issue with read access on the array itself, given the nature of the reference, but I'd say those points reinforce the use of my suggestion above, it avoids the COW issues, and avoids any issues with the data access I can't think of a reliable way to handle the read only status of array without breaking compatibility, or allocating more data somehow, but regardless I think this situation warrants at least a temporary local solution |
This also needs to be done for |
606ec2e
to
e7ca564
Compare
e7ca564
to
040ef6a
Compare
b778928
to
c15e83b
Compare
d9a34ce
to
6a2bab7
Compare
6a2bab7
to
b5da867
Compare
Indeed this solution is not perfect, and we should consider modifying how read-only arrays are implemented. I will try to think of a nice solution when I have more time. |
Made an issue tracking the broader issues of the read-only state: |
Use a duplicate of the passed array when it is read-only.
Prior to this fix, when the array was marked as read-only, the temporary address of
p_arguments->read_only
was used for all parameters. Consequently, this caused all parameters to reference the last element of the array.Fixes #93600.