-
Notifications
You must be signed in to change notification settings - Fork 7.8k
ext/spl: Fix various ArrayObject bugs #12037
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
base: master
Are you sure you want to change the base?
Conversation
ext/spl/spl_array.c
Outdated
if (check_inherited && intern->fptr_offset_set) { | ||
zval tmp; | ||
|
||
if (!offset) { | ||
ZVAL_NULL(&tmp); | ||
offset = &tmp; | ||
} | ||
zend_call_method_with_2_params(object, object->ce, &intern->fptr_offset_set, "offsetSet", NULL, offset, value); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be done in the !offset
branch as well: https://3v4l.org/AYJjF
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I understand what you are asking me to do here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the if (!offset) {
branch above, you need to call offsetSet()
if there is such method on the object. https://3v4l.org/AYJjF shows that offsetSet()
used to be called during $arrayObject[] = ...;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the code at https://3v4l.org/lO4Tf, this is the output on master:
string(12) "A::offsetSet"
string(12) "B::offsetSet"
and this is the output on this branch:
string(12) "A::offsetSet"
Is this an expected behavior change? If not, I think that we should move the if (check_inherited && intern->fptr_offset_set) {
block above if (!offset) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huuuum I think it is slightly problematic that an object that implements ArrayAccess supports appending as it is indistinguishable from $o[null]
but this is something I should add tests for in #12723
But I do agree that ArrayObject subclassing and ArrayAccess implementations should behave identically. Thanks for spotting this, I'm amending this and adding a test :)
ab665f5
to
2799ee9
Compare
I don't think this can go to 8.3 as it is quite late for such potentially breaking fixes considering that PR is also not ready at this stage (object leak and failed CI). Especially the append bit is a BC break even though I agree that it should be fixed but I would prefer 8.4 instead as this should be for sure in UPGRADING. Note that at this stage we should no longer do any changes that require adding note to UPGRADING. I would also prefer to add the Dynamic properties change to upgrading. You could argue that this should be done before and it is just an omission which is true but it wasn't done and users might be suprised if they see such change so I think each such changes should be explicitly mentioned in UPGRADING (deprecated functionality). You can see that this is already impacting one standard test so I guess some users will be impacted by this. |
a9da402
to
9ccfbb5
Compare
a42b71e
to
e44eb89
Compare
The code looks good to me except for the behavior change when offsetSet() is overridden (#12037 (comment)) |
…ect backing value This aligns the behaviour of calling it with the append() method
Although now there is a memory leak?
b9c5c47
to
127652f
Compare
I have mixed opinions about the change in 7e46992. On one hand it seems sensible and allows sub-classes to differentiate I would like to see what others think. |
This fixes:
new ArrayObject($targetObj);
#9432new ArrayObject($targetObject)
allows setting typed properties to invalid types #9434$ao[] = $v
ArrayObject is dealing with the property HashTable directly, this is not much of an issue for read, isset, and empty operations.
However, write operations are very different in that classes can impose restriction on those, ranging from visibility, types and dynamic properties.
Moreover, for some unknown reason, ArrayObject does not use the backing class overloaded property access magic methods and tests for this. Meaning, we cannot just use the standard
write_property
handler of the CE, thus we need to reimplement it ourself to dodge the__set()
call.Commit 1 is just code rearranging so that I could navigate this file more easily...