Fixes bugs #61967, #62607, #69068, #70713.
The primary changes are:
a) Use the ht_iterator mechanism to ensure safety not only if the
iterated array itself changes, but also if it is replaced (and
potentially destroyed) entirely. We use the same semantics for
behavior under modification as foreach-by-reference. In
particular, we advance to the next element before processing it.
If the iterated entity is exchanged we iterate the new one from
the start. If it is not an array/object we warn and abort.
b) Always create a reference to the current value. Previously the
code kept the value as a non-reference and updated it to the
reference value produced by the user callback. However this is
unsafe, as the array may have been reallocated in the meantime,
so the previous value pointer is no longer value.
c) Around a recursive walk, incref the reference containing the
array. This ensures that the location where the currently
iterated value is stored cannot be freed.
One problem I was not able to solve is that we cannot decrement
the apply count if the array is exchanged during a recursive walk.
Always duplicate the array before doing a sort with user-defined
comparison function, to avoid access to the intermediate
inconsistent state.
I've also dropped the "array modification" warning, as protection
against modifications is no longer relevant if we're always working
on a copy anyway.
This also required some changes to how SplArray forwards calls to
sorting functions.
* pull-request/1284:
Rename interface macros
Fix typo in UPGRADING
Move definition of Throwable to zend_exceptions.h/c
Check for zend_ce_throwable instead
Fix some missed tests
Add Throwable tests
Fix previous exception type check
Updated UPGRADING with RFC link
Changed AssertionException to AssertionError
Update exception error messages
Throwable method signatures.
Update exception names in tests after formatting changes.
Merge exception formatting changes.
Make zend_get_exception_base static.
Fix a few missed tests.
Fix handler double copy.
Updated tests to reflect exception class changes.
Remodel exceptions based on Throwable interface
This implements a reduced variant of #1226 with just the following
change:
-Fatal error: Uncaught exception 'EngineException' with message 'Call to private method foo::bar() from context ''' in %s:%d
+Fatal error: Uncaught EngineException: Call to private method foo::bar() from context '' in %s:%d
The '' wrapper around messages is very weird if the exception
message itself contains ''. Futhermore having the message wrapped
in '' doesn't work for the "and defined" suffix of
TypeExceptions.
TypeException stays as-is for now because it uses messages that are
incompatible with the way exception messages are displayed.
closure_038.phpt and a few others now show that we're generating
too many exceptions for compound operations on undefined properties
-- this needs to be fixed in a followup.