Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ PHP NEWS
- SimpleXML:
. Fixed integer element offsets that cannot resolve aliasing an existing
element. (iliaal)
. SimpleXMLElement::__construct() now raises a ValueError when the $data
argument contains NUL bytes. (iliaal)

- Standard:
. Added the "filter.max_filter_count" stream context option for php://filter
Expand Down
8 changes: 8 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ PHP 8.6 UPGRADE NOTES
SplFileObject::seek() past EOF now produces the same key() value as
SplTempFileObject; the two previously returned different values.

- SimpleXML:
. SimpleXMLElement::__construct() now raises a ValueError when the $data
argument contains NUL bytes, matching simplexml_load_file(). With
$dataIsURL set it previously truncated the path at the first NUL byte.
Without it the string went to libxml, which at default options rejects a
NUL on current versions but accepts the truncated document on older ones
and under LIBXML_RECOVER.

- Standard:
. array_intersect() with at least two arrays now converts values to strings
while scanning its inputs instead of during sort comparisons. This can
Expand Down
9 changes: 4 additions & 5 deletions ext/simplexml/simplexml.c
Original file line number Diff line number Diff line change
Expand Up @@ -2283,18 +2283,17 @@ PHP_FUNCTION(simplexml_load_string)
PHP_METHOD(SimpleXMLElement, __construct)
{
php_sxe_object *sxe = Z_SXEOBJ_P(ZEND_THIS);
char *data;
zend_string *data;
zend_string *ns = zend_empty_string;
size_t data_len;
xmlDocPtr docp;
zend_long options = 0;
bool is_url = false, isprefix = false;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lbSb", &data, &data_len, &options, &is_url, &ns, &isprefix) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|lbSb", &data, &options, &is_url, &ns, &isprefix) == FAILURE) {
RETURN_THROWS();
}

if (ZEND_SIZE_T_INT_OVFL(data_len)) {
if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(data))) {
zend_argument_error(zend_ce_exception, 1, "is too long");
RETURN_THROWS();
}
Expand All @@ -2308,7 +2307,7 @@ PHP_METHOD(SimpleXMLElement, __construct)
}

PHP_LIBXML_SANITIZE_GLOBALS(read_file_or_memory);
docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
docp = is_url ? xmlReadFile(ZSTR_VAL(data), NULL, (int)options) : xmlReadMemory(ZSTR_VAL(data), (int)ZSTR_LEN(data), NULL, NULL, (int)options);
PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory);

if (!docp) {
Expand Down
37 changes: 37 additions & 0 deletions ext/simplexml/tests/sxe_ctor_nul_path.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
SimpleXMLElement constructor rejects NUL bytes in $data
--EXTENSIONS--
simplexml
--FILE--
<?php
$tmp = tempnam(sys_get_temp_dir(), 'sxe');
file_put_contents($tmp, '<r/>');
$path = $tmp . "\0evil";

try {
new SimpleXMLElement($path, 0, true);
echo "url mode: loaded\n";
} catch (Throwable $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}

try {
new SimpleXMLElement("<r/>\0evil");
echo "data mode: loaded\n";
} catch (Throwable $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}

try {
simplexml_load_file($path);
echo "load_file: loaded\n";
} catch (Throwable $e) {
echo $e::class, ": ", $e->getMessage(), "\n";
}

unlink($tmp);
?>
--EXPECT--
ValueError: SimpleXMLElement::__construct(): Argument #1 ($data) must not contain any null bytes
ValueError: SimpleXMLElement::__construct(): Argument #1 ($data) must not contain any null bytes
ValueError: simplexml_load_file(): Argument #1 ($filename) must not contain any null bytes
Loading