Skip to content

Commit

Permalink
Fix DOMEntity field getter bugs
Browse files Browse the repository at this point in the history
- publicId could crash PHP if none was provided
- notationName never worked

The fields of this classs were untested. This new test file changes that.

Closes GH-11779.
  • Loading branch information
nielsdos committed Jul 24, 2023
1 parent 9fc0eab commit d439ee1
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 9 deletions.
3 changes: 3 additions & 0 deletions NEWS
Expand Up @@ -6,6 +6,9 @@ PHP NEWS
. Fixed bug GH-11716 (cli server crashes on SIGINT when compiled with
ZEND_RC_DEBUG=1). (nielsdos)

- DOM:
. Fix DOMEntity field getter bugs. (nielsdos)

- FFI:
. Fix leaking definitions when using FFI::cdef()->new(...). (ilutov)

Expand Down
20 changes: 11 additions & 9 deletions ext/dom/entity.c
Expand Up @@ -27,13 +27,13 @@
/*
* class DOMEntity extends DOMNode
*
* URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-527DCFF2
* URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-527DCFF2
* Since:
*/

/* {{{ publicId string
readonly=yes
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-D7303025
URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D7303025
Since:
*/
int dom_entity_public_id_read(dom_object *obj, zval *retval)
Expand All @@ -45,7 +45,7 @@ int dom_entity_public_id_read(dom_object *obj, zval *retval)
return FAILURE;
}

if (nodep->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
if (nodep->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY || !nodep->ExternalID) {
ZVAL_NULL(retval);
} else {
ZVAL_STRING(retval, (char *) (nodep->ExternalID));
Expand All @@ -58,7 +58,7 @@ int dom_entity_public_id_read(dom_object *obj, zval *retval)

/* {{{ systemId string
readonly=yes
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-D7C29F3E
URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D7C29F3E
Since:
*/
int dom_entity_system_id_read(dom_object *obj, zval *retval)
Expand All @@ -83,13 +83,12 @@ int dom_entity_system_id_read(dom_object *obj, zval *retval)

/* {{{ notationName string
readonly=yes
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-6ABAEB38
URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6ABAEB38
Since:
*/
int dom_entity_notation_name_read(dom_object *obj, zval *retval)
{
xmlEntity *nodep = (xmlEntity *) dom_object_get_node(obj);
char *content;

if (nodep == NULL) {
php_dom_throw_error(INVALID_STATE_ERR, 1);
Expand All @@ -99,9 +98,12 @@ int dom_entity_notation_name_read(dom_object *obj, zval *retval)
if (nodep->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
ZVAL_NULL(retval);
} else {
content = (char *) xmlNodeGetContent((xmlNodePtr) nodep);
ZVAL_STRING(retval, content);
xmlFree(content);
/* According to spec, NULL is only allowed for unparsed entities, if it's not set we should use the empty string. */
if (!nodep->content) {
ZVAL_EMPTY_STRING(retval);
} else {
ZVAL_STRING(retval, (const char *) nodep->content);
}
}

return SUCCESS;
Expand Down
100 changes: 100 additions & 0 deletions ext/dom/tests/DOMEntity_fields.phpt
@@ -0,0 +1,100 @@
--TEST--
DOMEntity fields
--EXTENSIONS--
dom
--FILE--
<?php
$xmlString = <<<XML
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY sampleInternalEntity "This is a sample entity value.">
<!ENTITY sampleExternalSystemWithNotationName SYSTEM "external.stuff" NDATA stuff>
<!ENTITY sampleExternalSystemWithoutNotationName SYSTEM "external.stuff" NDATA >
<!ENTITY sampleExternalPublicWithNotationName1 PUBLIC "public id" "external.stuff" NDATA stuff>
<!ENTITY sampleExternalPublicWithNotationName2 PUBLIC "" "external.stuff" NDATA stuff>
<!ENTITY sampleExternalPublicWithoutNotationName1 PUBLIC "public id" "external.stuff" NDATA >
<!ENTITY sampleExternalPublicWithoutNotationName2 PUBLIC "" "external.stuff" NDATA >
]>
<root/>
XML;

$dom = new DOMDocument();
$dom->loadXML($xmlString);

// Sort them, the iteration order isn't defined
$entities = iterator_to_array($dom->doctype->entities);
ksort($entities);

foreach ($entities as $entity) {
echo "Entity name: {$entity->nodeName}\n";
echo "publicId: ";
var_dump($entity->publicId);
echo "systemId: ";
var_dump($entity->systemId);
echo "notationName: ";
var_dump($entity->notationName);
echo "actualEncoding: ";
var_dump($entity->actualEncoding);
echo "encoding: ";
var_dump($entity->encoding);
echo "version: ";
var_dump($entity->version);
echo "\n";
}
?>
--EXPECT--
Entity name: sampleExternalPublicWithNotationName1
publicId: string(9) "public id"
systemId: string(14) "external.stuff"
notationName: string(5) "stuff"
actualEncoding: NULL
encoding: NULL
version: NULL

Entity name: sampleExternalPublicWithNotationName2
publicId: string(0) ""
systemId: string(14) "external.stuff"
notationName: string(5) "stuff"
actualEncoding: NULL
encoding: NULL
version: NULL

Entity name: sampleExternalPublicWithoutNotationName1
publicId: string(9) "public id"
systemId: string(14) "external.stuff"
notationName: string(0) ""
actualEncoding: NULL
encoding: NULL
version: NULL

Entity name: sampleExternalPublicWithoutNotationName2
publicId: string(0) ""
systemId: string(14) "external.stuff"
notationName: string(0) ""
actualEncoding: NULL
encoding: NULL
version: NULL

Entity name: sampleExternalSystemWithNotationName
publicId: NULL
systemId: string(14) "external.stuff"
notationName: string(5) "stuff"
actualEncoding: NULL
encoding: NULL
version: NULL

Entity name: sampleExternalSystemWithoutNotationName
publicId: NULL
systemId: string(14) "external.stuff"
notationName: string(0) ""
actualEncoding: NULL
encoding: NULL
version: NULL

Entity name: sampleInternalEntity
publicId: NULL
systemId: NULL
notationName: NULL
actualEncoding: NULL
encoding: NULL
version: NULL

0 comments on commit d439ee1

Please sign in to comment.