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
1 change: 0 additions & 1 deletion Zend/zend_call_stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ static bool zend_call_stack_get_freebsd(zend_call_stack *stack)
static bool zend_call_stack_get_win32(zend_call_stack *stack)
{
ULONG_PTR low_limit, high_limit;
ULONG size;
MEMORY_BASIC_INFORMATION guard_region = {0}, uncommitted_region = {0};
size_t result_size, page_size;

Expand Down
27 changes: 18 additions & 9 deletions ext/dom/dom_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ static void itemHashScanner (void *payload, void *data, xmlChar *name)
}
/* }}} */

static dom_nnodemap_object *php_dom_iterator_get_nnmap(const php_dom_iterator *iterator)
{
const zval *object = &iterator->intern.data;
dom_object *nnmap = Z_DOMOBJ_P(object);
return nnmap->ptr;
}

xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) /* {{{ */
{
xmlEntityPtr ret = xmlMalloc(sizeof(xmlEntity));
Expand Down Expand Up @@ -120,18 +127,22 @@ zval *php_dom_iterator_current_data(zend_object_iterator *iter) /* {{{ */
static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key) /* {{{ */
{
php_dom_iterator *iterator = (php_dom_iterator *)iter;
zval *object = &iterator->intern.data;
zend_class_entry *ce = Z_OBJCE_P(object);
dom_nnodemap_object *objmap = php_dom_iterator_get_nnmap(iterator);

/* Nodelists have the index as a key while named node maps have the name as a key. */
if (instanceof_function(ce, dom_nodelist_class_entry) || instanceof_function(ce, dom_modern_nodelist_class_entry)) {
/* Only dtd named node maps, i.e. the ones based on a libxml hash table or attribute collections,
* are keyed by the name because in that case the name is unique. */
if (!objmap->ht && objmap->nodetype != XML_ATTRIBUTE_NODE) {
ZVAL_LONG(key, iter->index);
} else {
dom_object *intern = Z_DOMOBJ_P(&iterator->curobj);

if (intern != NULL && intern->ptr != NULL) {
xmlNodePtr curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name));
xmlNodePtr curnode = ((php_libxml_node_ptr *)intern->ptr)->node;
if (objmap->nodetype == XML_ATTRIBUTE_NODE && php_dom_follow_spec_intern(intern)) {
ZVAL_NEW_STR(key, dom_node_get_node_name_attribute_or_element(curnode, false));
} else {
ZVAL_STRINGL(key, (const char *) curnode->name, xmlStrlen(curnode->name));
}
} else {
ZVAL_NULL(key);
}
Expand Down Expand Up @@ -169,9 +180,7 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
}

dom_object *intern = Z_DOMOBJ_P(&iterator->curobj);
zval *object = &iterator->intern.data;
dom_object *nnmap = Z_DOMOBJ_P(object);
dom_nnodemap_object *objmap = nnmap->ptr;
dom_nnodemap_object *objmap = php_dom_iterator_get_nnmap(iterator);

if (intern != NULL && intern->ptr != NULL) {
if (objmap->nodetype != XML_ENTITY_NODE &&
Expand Down
71 changes: 71 additions & 0 deletions ext/dom/tests/modern/xml/gh17572.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
--TEST--
GH-17572 (getElementsByTagName returns collections with tagName-based indexing, causing loss of elements when converted to arrays)
--EXTENSIONS--
dom
--FILE--
<?php

$dom = Dom\XMLDocument::createFromString(<<<XML
<!DOCTYPE root [
<!ENTITY a "a">
]>
<root>
<p/>
<p xmlns:x="urn:x" x:a="1" b="2" a="3"/>
</root>
XML);

echo "--- querySelectorAll('p') ---\n";

foreach ($dom->querySelectorAll('p') as $k => $v) {
var_dump($k, $v->nodeName);
}

echo "--- getElementsByTagName('p') ---\n";

foreach ($dom->getElementsByTagName('p') as $k => $v) {
var_dump($k, $v->nodeName);
}

echo "--- entities ---\n";

foreach ($dom->doctype->entities as $k => $v) {
var_dump($k, $v->nodeName);
}

echo "--- attributes ---\n";

$attribs = $dom->getElementsByTagName('p')[1]->attributes;
foreach ($attribs as $k => $v) {
var_dump($k, $v->value);
var_dump($attribs[$k]->value);
}

?>
--EXPECT--
--- querySelectorAll('p') ---
int(0)
string(1) "p"
int(1)
string(1) "p"
--- getElementsByTagName('p') ---
int(0)
string(1) "p"
int(1)
string(1) "p"
--- entities ---
string(1) "a"
string(1) "a"
--- attributes ---
string(7) "xmlns:x"
string(5) "urn:x"
string(5) "urn:x"
string(3) "x:a"
string(1) "1"
string(1) "1"
string(1) "b"
string(1) "2"
string(1) "2"
string(1) "a"
string(1) "3"
string(1) "3"
57 changes: 57 additions & 0 deletions ext/pdo/tests/pdo_fetch_class_opaque_object.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
--TEST--
PDO Common: Attempting to initialize an opaque object via PDO::FETCH_CLASS
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();

$db->exec('CREATE TABLE pdo_fetch_class_opaque_object(id int NOT NULL PRIMARY KEY, path VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_class_opaque_object VALUES(1, 'AA')");
$db->exec("INSERT INTO pdo_fetch_class_opaque_object VALUES(2, 'BB')");
$db->exec("INSERT INTO pdo_fetch_class_opaque_object VALUES(3, 'CC')");

$stmt = $db->prepare('SELECT path FROM pdo_fetch_class_opaque_object');
$stmt->execute();

var_dump($stmt->fetchAll(PDO::FETCH_CLASS, 'Directory', []));
?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_class_opaque_object");
?>
--EXPECTF--
array(3) {
[0]=>
object(Directory)#%s (1) {
["path"]=>
string(2) "AA"
["handle"]=>
uninitialized(mixed)
}
[1]=>
object(Directory)#%s (1) {
["path"]=>
string(2) "BB"
["handle"]=>
uninitialized(mixed)
}
[2]=>
object(Directory)#%s (1) {
["path"]=>
string(2) "CC"
["handle"]=>
uninitialized(mixed)
}
}
55 changes: 55 additions & 0 deletions ext/pdo/tests/pdo_fetch_function_exception_in_call.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--TEST--
PDO Common: PDO::FETCH_FUNC with a call that throws an exception for one specific value
--EXTENSIONS--
pdo
--SKIPIF--
<?php
$dir = getenv('REDIR_TEST_DIR');
if (false == $dir) die('skip no driver');
require_once $dir . 'pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
if (getenv('REDIR_TEST_DIR') === false) putenv('REDIR_TEST_DIR='.__DIR__ . '/../../pdo/tests/');
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();

$db->exec('CREATE TABLE pdo_fetch_function_exception_in_call(id int NOT NULL PRIMARY KEY, val1 VARCHAR(10), val2 VARCHAR(10))');
$db->exec("INSERT INTO pdo_fetch_function_exception_in_call VALUES(1, 'A', 'alpha')");
$db->exec("INSERT INTO pdo_fetch_function_exception_in_call VALUES(2, 'B', 'beta')");
$db->exec("INSERT INTO pdo_fetch_function_exception_in_call VALUES(3, 'C', 'gamma')");
$db->exec("INSERT INTO pdo_fetch_function_exception_in_call VALUES(4, 'D', 'delta')");

$selectVals = $db->prepare('SELECT val1, val2 FROM pdo_fetch_function_exception_in_call');

function bogusCallback(string $val1, string $val2) {
$r = $val1 . ': ' . $val2 . PHP_EOL;
echo $r;
if ($val2 === 'gamma') {
throw new Exception("GAMMA IS BAD");
}
return $val1 . ': ' . $val2;
}

$selectVals->execute();

try {
$result = $selectVals->fetchAll(PDO::FETCH_FUNC, 'bogusCallback');
var_dump($result);
} catch (Throwable $e) {
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
}

?>
--CLEAN--
<?php
require_once getenv('REDIR_TEST_DIR') . 'pdo_test.inc';
$db = PDOTest::factory();
PDOTest::dropTableIfExists($db, "pdo_fetch_function_exception_in_call");
?>
--EXPECT--
A: alpha
B: beta
C: gamma
Exception: GAMMA IS BAD
Loading