Currently, internal classes are registered with the following code:
INIT_CLASS_ENTRY(ce, "InternalClass", class_InternalClass_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ...;
This has worked well so far, except if InternalClass is readonly. It is because some inheritance checks are run by zend_register_internal_class_ex before ZEND_ACC_READONLY_CLASS is added to ce_flags.
The issue is fixed by adding a zend_register_internal_class_with_flags() zend API function that stubs can use from now on. This function makes sure to add the flags before running any checks. Since the new API is not available in lower PHP versions, gen_stub.php has to keep support for the existing API for PHP 8.3 and below.
Since GCC 12.x, using getThis() in a conditional yields a warning:
<source>:12:22: warning: the comparison will always evaluate as 'true' for
the address of 'This' will never be NULL [-Waddress]
12 | return getThis() ? 2 : 3;
| ^
Commit d86314939c added an additional parameter to Z_PARAM_FUNC_EX.
To maintain compatibility with third-party extensions, we keep
Z_PARAM_FUNC_EX as it used to be, and add Z_PARAM_FUNC_EX2 instead.
When we try to load an extension multiple times, we still overwrite the
type, module number, and handle. If the module number is used to
indicate module boundaries (e.g. in reflection and in dom, see e.g.
dom_objects_set_class_ex), then all sorts of errors can happen.
In the case of ext/dom, OP's error happens because the following
happens:
- The property handler is set up incorrectly in
dom_objects_set_class_ex() because the wrong module number is
specified. The class highest in the hierarchy is DOMNode, so the
property handler is incorrectly set to that of DOMNode instead of
DOMDocument.
- The documentElement property doesn't exist on DOMNode, it only exists
on DOMDocument, so it tries to read using zend_std_read_property().
As there is no user property called documentElement, that read
operation returns an undef value.
However, the type is still checked, resulting in the strange exception.
Solve this by changing the API such that the data is only overwritten if
it's owned data.
Closes GH-12246.
This API handles the common case of calling a userland function and passing a return value pointer.
This allows to remove the 'incorrect' usage of zend_fcall_info_call(fci, fcc, retval, NULL)
Object handlers being separate from class entries is a legacy inherited from PHP 5. Today it has little benefit to keep them separate: in fact, accessing object handlers usually requires not-so-safe hacks.
While it is possible to swap handlers in a custom installed create_object handler, this mostly is tedious, as well as it requires allocating the object handlers struct at runtime, possibly caching it etc..
This allows extensions, which intend to observe other classes to install their own class handlers.
The life cycle of internal classes may now be simply observed by swapping the class handlers in post_startup stage.
The life cycle of userland classes may be observed by iterating over the new classes in zend_compile_file and zend_compile_string and then swapping their handlers.
In general, this would also be a first step in directly tying the object handlers to classes. Especially given that I am not aware of any case where the object handlers would be different between various instances of a given class.
Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
Add libxml_get_external_entity_loader(), which returns the currently
installed external entity loader, i.e. the value which was passed to
libxml_set_external_entity_loader() or null if no loader was installed
and the default entity loader will be used.
This allows libraries to save and restore the loader, controlling entity
expansion without interfering with the rest of the application.
Add macro Z_PARAM_FUNC_OR_NULL_WITH_ZVAL(). This allows us to get the
zval for a callable parameter without duplicating callable argument
parsing.
The saved zval keeps the object needed for fcc/fci alive, simplifying
memory management.
Fixes#76763.
This doesn't have an effect really, but humans and IDEs can struggle to see through the macro soup when they first interact with PHP's source code.
Moreover, this reduces some of the macro expansion hell when they appear in compiler warnings.
Implements https://wiki.php.net/rfc/partially-supported-callables-expand-deprecation-notices
so that uses of "self" and "parent" in is_callable() and callable
type constraints now raise a deprecation notice, independent of the
one raised when and if the callable is actually invoked.
A new flag is added to the existing check_flags parameter of
zend_is_callable / zend_is_callable_ex, for use in internal calls
that would otherwise repeat the notice multiple times. In particular,
arguments to internal function calls are checked first based on
arginfo, and then again during ZPP, so the former suppresses the
deprecation notice.
Some existing tests which raised this deprecation have been updated
to avoid the syntax, but the existing version retained for maximum
regression coverage until it is made an error.
With thanks to Juliette Reinders Folmer for the RFC and initial
investigation.
Closes GH-8823.
A slight imperfection in https://github.com/php/php-src/pull/7443.
As a zend_API, we should also consider other extensions that may call it in methods. This change will not break the behavior of php-src.