Since the GH-24050 fix, gc_collect_white() adds the table returned by
get_gc to the garbage buffer. sxe_object_free_storage() released
sxe->properties with zend_hash_release(), which does not remove the
table from the GC buffer, so the GC later read and freed it again.
Use zend_array_release(), which goes through zend_array_destroy().
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Close GH-24494
- Replace bailout on OOM with UnwindExit
- Properly reset various globals that may be accessed during startup
Fix GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
Fix GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
Co-authored-by: Ilija Tovilo <ilija.tovilo@me.com>
Co-authored-by: Jakub Zelenka <bukka@php.net>
Co-authored-by: Nora Dossche <7771979+ndossche@users.noreply.github.com>
Co-authored-by: Nicolas Grekas <nicolas.grekas@gmail.com>
Property proxies like $xml->first store the parent node plus an element
iterator name. sxe_objects_compare compared the parent wrappers, so
sibling proxies always compared equal. Resolve each side through
php_sxe_get_first_node_non_destructive before comparing. When both sides
resolve to no node, keep comparing the parent wrappers, so two empty
results from the same parent still compare equal.
Fixes GH-12171
Closes GH-23187
addChild() passed the caller's prefix to node_as_zval_str() with isprefix
set to 0, so the returned element filtered its children by comparing that
prefix against the namespace href and matched nothing. Take the prefix from
the created node and mark it as one, but only when the caller asked for a
namespace, so a plain addChild() keeps the unfiltered view that its
attributes and non-namespaced children rely on.
Closes GH-23599
sxe_prop_dim_write() overwrote the element node with the first attribute
node when resolving an SXE_ITER_ATTRLIST iterator, so xmlNewProp() targeted
a non-element node and was skipped entirely when no attribute existed yet.
Keep the element node in place and resolve only the attribute list start,
so $x->attributes()["new"] = "v" creates the attribute like the symmetric
$x["new"] path; property writes on the attributes() object share the fixed
path while read/exists/unset handlers are unaffected by this defect.
Closes GH-23500
sxe_objects_compare dereferenced document->ptr when both nodes were
NULL without checking document. A subclass that skips parent
__construct leaves document NULL, so $a == $b segfaulted. Compare the
documents only when both are set; anything else is uncomparable.
Closes GH-23067
With dataIsURL set the first argument goes to xmlReadFile as a C string,
so new SimpleXMLElement("/tmp/ok.xml\0evil", 0, true) truncates at the NUL
and quietly loads /tmp/ok.xml. simplexml_load_file() and
SimpleXMLElement::asXML() already declare their path argument as a path;
the constructor took a plain string, so the check never ran.
Closes GH-23069
sxe_get_element_by_offset scanned with nodendx <= offset, so a negative
offset skipped the loop and returned the node it started from, and the
SXE_ITER_NONE branches of the read and write handlers aliased the node
for every offset other than 0. Reads and isset() reported an existing
element and writes overwrote it. An offset that resolves to no element
now warns and leaves the document alone.
Closes GH-23068
If only we did not have the pseudo-key "@attributes", we could've just
removed the custom get_debug_info implementation and this would work out
of the box. Anyway, we just have to manually check for an override now.
Closes GH-20131.
Normally, simplexml cannot import document nodes,
but xsl allows to circumvent this.
A document does not have a name, so we return the empty string
in that case.
While we could add an explicit check, we might as well switch
the macro to a form that would be more optimal anyway as many
tag names can be single characters.
The test was added in xsl because adding it in simplexml would
break out-of-tree builds of simplexml.
Closes GH-19990.
In the macOS 26 SDK, xmlFree is defined as a macro for free. This causes
issues where a same-named variable is used. Renaming the variable to
should_free resolves the issue.
See:
$ grep -B4 -A2 -n "#define xmlFree(" "Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.sdk/usr/include/libxml/globals.h"
261-#if defined(LIBXML_HAS_DEPRECATED_MEMORY_ALLOCATION_FUNCTIONS)
262-#define xmlMalloc(size) malloc(size)
263-#define xmlMallocAtomic(size) malloc(size)
264-#define xmlRealloc(ptr, size) realloc((ptr), (size))
265:#define xmlFree(ptr) free(ptr)
266-#define xmlMemStrdup(str) strdup(str)
267-#endif
Fixes:
```
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk/usr/include/libxml/xmlIO.h:117,
from /Library/Developer/CommandLineTools/SDKs/MacOSX26.sdk/usr/include/libxml/parser.h:813,
from /private/tmp/php-20250914-13349-uqsk5o/php-8.4.12/ext/dom/php_dom.h:29,
from /private/tmp/php-20250914-13349-uqsk5o/php-8.4.12/ext/dom/attr.c:26:
/private/tmp/php-20250914-13349-uqsk5o/php-8.4.12/ext/dom/attr.c: In function 'dom_compare_value':
/private/tmp/php-20250914-13349-uqsk5o/php-8.4.12/ext/dom/attr.c:208:17: error: called object 'free' is not a function or function pointer
208 | xmlFree(attr_value);
| ^~~~~~~
/private/tmp/php-20250914-13349-uqsk5o/php-8.4.12/ext/dom/attr.c:204:14: note: declared here
204 | bool free;
| ^~~~
make: *** [ext/dom/attr.lo] Error 1
```
Closes GH-19832.
Signed-off-by: Ruoyu Zhong <zhongruoyu@outlook.com>
xmlSave() also can flush in some cases. When the encoding is not
available this can fail for short inputs, resulting in an empty string
which is interned but then wrongly tagged by RETURN_NEW_STR.
Fix this by checking the error condition and switching to RETURN_STR for
defense-in-depth.
This issue also exists on 8.3, but does not crash; however, due to the
different API usage internally I cannot easily fix it on 8.3. There it
gives a partial output.
Closes GH-18606.
* PHP-8.4:
Fix GH-18309: ipv6 filter integer overflow
Fix GH-18304: Changing the properties of a DateInterval through dynamic properties triggers a SegFault
* PHP-8.3:
Fix GH-18309: ipv6 filter integer overflow
Fix GH-18304: Changing the properties of a DateInterval through dynamic properties triggers a SegFault
For dynamic fetches the cache_slot will be NULL, so we have to check for
that when resetting the cache. For zip and xmlreader this couldn't
easily be tested because of a lack of writable properties.
Closes GH-18307.
The cache slot for FETCH_OBJ_W in function `test` is primed with the
class for C. The next call uses a simplexml instance and reuses the same
cache slot. simplexml's get_property_ptr handler does not use the cache
slot, so the old values remain in the cache slot. When
`zend_handle_fetch_obj_flags` is called this is not guarded by a check
for the class entry. So we end up using the prop_info from the property
C::$a instead of the simplexml property.
This patch adds a reset to the cache slots in the property address fetch
code and also in the extensions with a non-standard reference handler.
This keeps the run time cache consistent and avoids the issue without
complicating the fast paths.
Closes GH-17739.