Skip to content

Commit d439ee1

Browse files
committed
Fix DOMEntity field getter bugs
- 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.
1 parent 9fc0eab commit d439ee1

File tree

3 files changed

+114
-9
lines changed

3 files changed

+114
-9
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ PHP NEWS
66
. Fixed bug GH-11716 (cli server crashes on SIGINT when compiled with
77
ZEND_RC_DEBUG=1). (nielsdos)
88

9+
- DOM:
10+
. Fix DOMEntity field getter bugs. (nielsdos)
11+
912
- FFI:
1013
. Fix leaking definitions when using FFI::cdef()->new(...). (ilutov)
1114

ext/dom/entity.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@
2727
/*
2828
* class DOMEntity extends DOMNode
2929
*
30-
* URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-527DCFF2
30+
* URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-527DCFF2
3131
* Since:
3232
*/
3333

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

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

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

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

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

107109
return SUCCESS;

ext/dom/tests/DOMEntity_fields.phpt

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
--TEST--
2+
DOMEntity fields
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
$xmlString = <<<XML
8+
<?xml version="1.0"?>
9+
<!DOCTYPE test [
10+
<!ENTITY sampleInternalEntity "This is a sample entity value.">
11+
<!ENTITY sampleExternalSystemWithNotationName SYSTEM "external.stuff" NDATA stuff>
12+
<!ENTITY sampleExternalSystemWithoutNotationName SYSTEM "external.stuff" NDATA >
13+
<!ENTITY sampleExternalPublicWithNotationName1 PUBLIC "public id" "external.stuff" NDATA stuff>
14+
<!ENTITY sampleExternalPublicWithNotationName2 PUBLIC "" "external.stuff" NDATA stuff>
15+
<!ENTITY sampleExternalPublicWithoutNotationName1 PUBLIC "public id" "external.stuff" NDATA >
16+
<!ENTITY sampleExternalPublicWithoutNotationName2 PUBLIC "" "external.stuff" NDATA >
17+
]>
18+
<root/>
19+
XML;
20+
21+
$dom = new DOMDocument();
22+
$dom->loadXML($xmlString);
23+
24+
// Sort them, the iteration order isn't defined
25+
$entities = iterator_to_array($dom->doctype->entities);
26+
ksort($entities);
27+
28+
foreach ($entities as $entity) {
29+
echo "Entity name: {$entity->nodeName}\n";
30+
echo "publicId: ";
31+
var_dump($entity->publicId);
32+
echo "systemId: ";
33+
var_dump($entity->systemId);
34+
echo "notationName: ";
35+
var_dump($entity->notationName);
36+
echo "actualEncoding: ";
37+
var_dump($entity->actualEncoding);
38+
echo "encoding: ";
39+
var_dump($entity->encoding);
40+
echo "version: ";
41+
var_dump($entity->version);
42+
echo "\n";
43+
}
44+
?>
45+
--EXPECT--
46+
Entity name: sampleExternalPublicWithNotationName1
47+
publicId: string(9) "public id"
48+
systemId: string(14) "external.stuff"
49+
notationName: string(5) "stuff"
50+
actualEncoding: NULL
51+
encoding: NULL
52+
version: NULL
53+
54+
Entity name: sampleExternalPublicWithNotationName2
55+
publicId: string(0) ""
56+
systemId: string(14) "external.stuff"
57+
notationName: string(5) "stuff"
58+
actualEncoding: NULL
59+
encoding: NULL
60+
version: NULL
61+
62+
Entity name: sampleExternalPublicWithoutNotationName1
63+
publicId: string(9) "public id"
64+
systemId: string(14) "external.stuff"
65+
notationName: string(0) ""
66+
actualEncoding: NULL
67+
encoding: NULL
68+
version: NULL
69+
70+
Entity name: sampleExternalPublicWithoutNotationName2
71+
publicId: string(0) ""
72+
systemId: string(14) "external.stuff"
73+
notationName: string(0) ""
74+
actualEncoding: NULL
75+
encoding: NULL
76+
version: NULL
77+
78+
Entity name: sampleExternalSystemWithNotationName
79+
publicId: NULL
80+
systemId: string(14) "external.stuff"
81+
notationName: string(5) "stuff"
82+
actualEncoding: NULL
83+
encoding: NULL
84+
version: NULL
85+
86+
Entity name: sampleExternalSystemWithoutNotationName
87+
publicId: NULL
88+
systemId: string(14) "external.stuff"
89+
notationName: string(0) ""
90+
actualEncoding: NULL
91+
encoding: NULL
92+
version: NULL
93+
94+
Entity name: sampleInternalEntity
95+
publicId: NULL
96+
systemId: NULL
97+
notationName: NULL
98+
actualEncoding: NULL
99+
encoding: NULL
100+
version: NULL

0 commit comments

Comments
 (0)