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: 1 addition & 1 deletion EXTENSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ STATUS: Working
-------------------------------------------------------------------------------
EXTENSION: random
PRIMARY MAINTAINER Go Kudo <[email protected]> (2022 - 2024)
Tim Düsterhus <[email protected]> (2022 - 2024)
Tim Düsterhus <[email protected]> (2022 - 2025)
MAINTENANCE: Maintained
STATUS: Working
SINCE: 8.2.0
Expand Down
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ PHP NEWS
or a TypeError if read_and_close value is not compatible with int.
(David Carlier)

- SimpleXML:
. Fixed bug GH-12231 (SimpleXML xpath should warn when returning other return
types than node lists). (nielsdos)

- SNMP:
. snmpget, snmpset, snmp_get2, snmp_set2, snmp_get3, snmp_set3 and
SNMP::__construct() throw an exception on invalid hostname, community
Expand Down
5 changes: 5 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ PHP 8.5 UPGRADE NOTES
. A ValueError is now thrown when trying to set a cursor name that is too
long on a PDOStatement resulting from the Firebird driver.

- SimpleXML:
- Passing an XPath expression that returns something other than a node set
to SimpleXMLElement::xpath() will now emit a warning and return false,
instead of silently failing and returning an empty array.

- SPL:
. ArrayObject no longer accepts enums, as modifying the $name or $value
properties can break engine assumptions.
Expand Down
21 changes: 17 additions & 4 deletions Zend/Optimizer/compact_literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
HashTable hash;
zend_string *key = NULL;
void *checkpoint = zend_arena_checkpoint(ctx->arena);
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot;
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot, *jmp_slot;

if (op_array->last_literal) {
info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info));
Expand All @@ -175,6 +175,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
end = opline + op_array->last;
while (opline < end) {
switch (opline->opcode) {
case ZEND_JMP_FRAMELESS:
LITERAL_INFO(opline->op1.constant, 1);
break;
case ZEND_INIT_FCALL_BY_NAME:
LITERAL_INFO(opline->op2.constant, 2);
break;
Expand Down Expand Up @@ -480,13 +483,14 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
zend_hash_clean(&hash);
op_array->last_literal = j;

const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int));
memset(const_slot, -1, j * 6 * sizeof(int));
const_slot = zend_arena_alloc(&ctx->arena, j * 7 * sizeof(int));
memset(const_slot, -1, j * 7 * sizeof(int));
class_slot = const_slot + j;
func_slot = class_slot + j;
bind_var_slot = func_slot + j;
property_slot = bind_var_slot + j;
method_slot = property_slot + j;
jmp_slot = method_slot + j;

/* Update opcodes to use new literals table */
cache_size = zend_op_array_extension_handles * sizeof(void*);
Expand Down Expand Up @@ -773,10 +777,19 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
break;
case ZEND_DECLARE_ANON_CLASS:
case ZEND_DECLARE_CLASS_DELAYED:
case ZEND_JMP_FRAMELESS:
opline->extended_value = cache_size;
cache_size += sizeof(void *);
break;
case ZEND_JMP_FRAMELESS:
// op1 func
if (jmp_slot[opline->op1.constant] >= 0) {
opline->extended_value = jmp_slot[opline->op1.constant];
} else {
opline->extended_value = cache_size;
cache_size += sizeof(void *);
jmp_slot[opline->op1.constant] = opline->extended_value;
}
break;
case ZEND_SEND_VAL:
case ZEND_SEND_VAL_EX:
case ZEND_SEND_VAR:
Expand Down
12 changes: 10 additions & 2 deletions ext/dom/html5_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ static lexbor_libxml2_bridge_status lexbor_libxml2_bridge_convert(
* If a prefix:name format is used, then the local name will be "prefix:name" and the prefix will be empty.
* There is however still somewhat of a concept of namespaces. There are three: HTML (the default), SVG, and MATHML. */
lxb_dom_element_t *element = lxb_dom_interface_element(node);
const lxb_char_t *name = lxb_dom_element_local_name(element, NULL);
const lxb_char_t *name = lxb_dom_element_qualified_name(element, NULL);
ZEND_ASSERT(!element->node.prefix);

xmlNodePtr lxml_element = xmlNewDocNode(lxml_doc, NULL, name, NULL);
if (UNEXPECTED(lxml_element == NULL)) {
retval = LEXBOR_LIBXML2_BRIDGE_STATUS_OOM;
Expand Down Expand Up @@ -203,7 +205,13 @@ static lexbor_libxml2_bridge_status lexbor_libxml2_bridge_convert(
for (lxb_dom_attr_t *attr = element->first_attr; attr != NULL; attr = attr->next) {
/* Same namespace remark as for elements */
size_t local_name_length, value_length;
const lxb_char_t *local_name = lxb_dom_attr_local_name(attr, &local_name_length);
const lxb_char_t *local_name = lxb_dom_attr_qualified_name(attr, &local_name_length);
if (attr->node.prefix) {
const char *pos = strchr((const char *) local_name, ':');
if (EXPECTED(pos)) {
local_name = (const lxb_char_t *) pos + 1;
}
}
const lxb_char_t *value = lxb_dom_attr_value(attr, &value_length);

if (UNEXPECTED(local_name_length >= INT_MAX || value_length >= INT_MAX)) {
Expand Down
18 changes: 18 additions & 0 deletions ext/dom/tests/modern/html/parser/gh18090.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
GH-18090 (Svg attributes and tag names are being lowercased)
--EXTENSIONS--
dom
--FILE--
<?php
echo \Dom\HTMLDocument::createFromString('<html><body><svg VIEWBOX="1 2 3 4"></svg></html>', LIBXML_NOERROR)->saveHTML(), "\n";

echo \Dom\HTMLDocument::createFromString('<html><body CLASS="no"><svg VIEWBOX="1 2 3 4"><feSpotLight x="10" y="10" z="50" pointsAtX="100" pointsAtY="100" limitingConeAngle="
10" /></svg></html>', LIBXML_NOERROR)->saveHTML(), "\n";

echo \Dom\HTMLDocument::createFromString('<html><body><svg VIEWBOX="1 2 3 4"></svg></html>', LIBXML_NOERROR)->querySelector('svg')->attributes[0]->name, "\n";
?>
--EXPECT--
<html><head></head><body><svg viewBox="1 2 3 4"></svg></body></html>
<html><head></head><body class="no"><svg viewBox="1 2 3 4"><feSpotLight x="10" y="10" z="50" pointsAtX="100" pointsAtY="100" limitingConeAngle="
10"></feSpotLight></svg></body></html>
viewBox
6 changes: 3 additions & 3 deletions ext/dom/tests/modern/html/parser/predefined_namespaces.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ echo $dom->saveXml();
svg http://www.w3.org/2000/svg
Attribute: width (NONE)
Attribute: height (NONE)
Attribute: viewbox (NONE)
Attribute: viewBox (NONE)
rect http://www.w3.org/2000/svg
Attribute: id (NONE)
Attribute: x (NONE)
Expand All @@ -65,7 +65,7 @@ svg http://www.w3.org/1998/Math/MathML
<title>Test</title>
</head>
<body>
<svg width="100" height="100" viewbox="0 0 4 2">
<svg width="100" height="100" viewBox="0 0 4 2">
<rect id="rectangle" x="10" y="20" width="90" height="60">
</rect>
</svg>
Expand All @@ -85,7 +85,7 @@ svg http://www.w3.org/1998/Math/MathML
<title>Test</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewbox="0 0 4 2">
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 4 2">
<rect id="rectangle" x="10" y="20" width="90" height="60">
</rect>
</svg>
Expand Down
22 changes: 22 additions & 0 deletions ext/simplexml/simplexml.c
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,21 @@ static int sxe_objects_compare(zval *object1, zval *object2) /* {{{ */
}
/* }}} */

static const char *sxe_get_object_type_name(xmlXPathObjectType type)
{
switch (type) {
case XPATH_BOOLEAN: return "bool";
case XPATH_NUMBER: return "number";
case XPATH_STRING: return "string";
#ifdef LIBXML_XPTR_LOCS_ENABLED
case XPATH_POINT: return "point";
case XPATH_RANGE: return "range";
case XPATH_LOCATIONSET: return "location set";
#endif
default: return "undefined";
}
}

/* {{{ Runs XPath query on the XML data */
PHP_METHOD(SimpleXMLElement, xpath)
{
Expand Down Expand Up @@ -1271,6 +1286,13 @@ PHP_METHOD(SimpleXMLElement, xpath)
RETURN_FALSE;
}

if (UNEXPECTED(retval->type != XPATH_NODESET)) {
php_error_docref(NULL, E_WARNING, "XPath expression must return a node set, %s returned",
sxe_get_object_type_name(retval->type));
xmlXPathFreeObject(retval);
RETURN_FALSE;
}

result = retval->nodesetval;

if (result != NULL) {
Expand Down
7 changes: 4 additions & 3 deletions ext/simplexml/tests/008.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ array(1) {
}
}
}
array(0) {
}

Warning: SimpleXMLElement::xpath(): Invalid expression in %s on line %d%A
Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, number returned in %s on line %d
bool(false)

Warning: SimpleXMLElement::xpath(): Invalid expression in %s on line %d
bool(false)
26 changes: 26 additions & 0 deletions ext/simplexml/tests/gh12231.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
GH-12231 (SimpleXML xpath should warn when returning other return types than node lists)
--EXTENSIONS--
simplexml
--FILE--
<?php

$xml = "<container><foo/><foo/></container>";
$sxe = simplexml_load_string($xml);

var_dump($sxe->xpath("count(//foo)"));
var_dump($sxe->xpath("string(//foo)"));
var_dump($sxe->xpath("boolean(//foo)"));
var_dump(count($sxe->xpath("//foo")));

?>
--EXPECTF--
Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, number returned in %s on line %d
bool(false)

Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, string returned in %s on line %d
bool(false)

Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, bool returned in %s on line %d
bool(false)
int(2)