Skip to content

Commit f902005

Browse files
author
Rob Richards
committed
MFH: fix bug #46699: (xml_parse crash when parser is namespace aware)
fix a couple warnings add test
1 parent 22955ad commit f902005

File tree

2 files changed

+107
-3
lines changed

2 files changed

+107
-3
lines changed

ext/xml/compat.c

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ _qualify_namespace(XML_Parser parser, const xmlChar *name, const xmlChar *URI, x
4040
/* Use libxml functions otherwise its memory deallocation is screwed up */
4141
*qualified = xmlStrdup(URI);
4242
*qualified = xmlStrncat(*qualified, parser->_ns_seperator, 1);
43-
*qualified = xmlStrncat(*qualified, name, strlen(name));
43+
*qualified = xmlStrncat(*qualified, name, xmlStrlen(name));
4444
} else {
4545
*qualified = xmlStrdup(name);
4646
}
@@ -104,7 +104,66 @@ _start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix
104104
y = 0;
105105
}
106106

107-
if (parser->h_start_element == NULL && parser->h_default == NULL) {
107+
if (parser->h_start_element == NULL) {
108+
if (parser->h_default) {
109+
110+
if (prefix) {
111+
qualified_name = xmlStrncatNew((xmlChar *)"<", prefix, xmlStrlen(prefix));
112+
qualified_name = xmlStrncat(qualified_name, (xmlChar *)":", 1);
113+
qualified_name = xmlStrncat(qualified_name, name, xmlStrlen(name));
114+
} else {
115+
qualified_name = xmlStrncatNew((xmlChar *)"<", name, xmlStrlen(name));
116+
}
117+
118+
if (namespaces) {
119+
int i, j;
120+
for (i = 0,j = 0;j < nb_namespaces;j++) {
121+
int ns_len;
122+
char *ns_string, *ns_prefix, *ns_url;
123+
124+
ns_prefix = (char *) namespaces[i++];
125+
ns_url = (char *) namespaces[i++];
126+
127+
if (ns_prefix) {
128+
ns_len = spprintf(&ns_string, 0, " xmlns:%s=\"%s\"", ns_prefix, ns_url);
129+
} else {
130+
ns_len = spprintf(&ns_string, 0, " xmlns=\"%s\"", ns_url);
131+
}
132+
qualified_name = xmlStrncat(qualified_name, (xmlChar *)ns_string, ns_len);
133+
134+
efree(ns_string);
135+
}
136+
}
137+
138+
if (attributes) {
139+
for (i = 0; i < nb_attributes; i += 1) {
140+
int att_len;
141+
char *att_string, *att_name, *att_value, *att_prefix, *att_valueend;
142+
143+
att_name = (char *) attributes[y++];
144+
att_prefix = (char *)attributes[y++];
145+
y++;
146+
att_value = (char *)attributes[y++];
147+
att_valueend = (char *)attributes[y++];
148+
149+
if (att_prefix) {
150+
att_len = spprintf(&att_string, 0, " %s:%s=\"", att_prefix, att_name);
151+
} else {
152+
att_len = spprintf(&att_string, 0, " %s=\"", att_name);
153+
}
154+
155+
qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_string, att_len);
156+
qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_value, att_valueend - att_value);
157+
qualified_name = xmlStrncat(qualified_name, (xmlChar *)"\"", 1);
158+
159+
efree(att_string);
160+
}
161+
162+
}
163+
qualified_name = xmlStrncat(qualified_name, (xmlChar *)">", 1);
164+
parser->h_default(parser->user, (const XML_Char *) qualified_name, xmlStrlen(qualified_name));
165+
xmlFree(qualified_name);
166+
}
108167
return;
109168
}
110169
_qualify_namespace(parser, name, URI, &qualified_name);
@@ -178,6 +237,18 @@ _end_element_handler_ns(void *user, const xmlChar *name, const xmlChar * prefix,
178237
XML_Parser parser = (XML_Parser) user;
179238

180239
if (parser->h_end_element == NULL) {
240+
if (parser->h_default) {
241+
char *end_element;
242+
int end_element_len;
243+
244+
if (prefix) {
245+
end_element_len = spprintf(&end_element, 0, "</%s:%s>", (char *) prefix, (char *)name);
246+
} else {
247+
end_element_len = spprintf(&end_element, 0, "</%s>", (char *)name);
248+
}
249+
parser->h_default(parser->user, (const XML_Char *) end_element, end_element_len);
250+
efree(end_element);
251+
}
181252
return;
182253
}
183254

@@ -212,7 +283,7 @@ _pi_handler(void *user, const xmlChar *target, const xmlChar *data)
212283
if (parser->h_default) {
213284
char *full_pi;
214285
spprintf(&full_pi, 0, "<?%s %s?>", (char *)target, (char *)data);
215-
parser->h_default(parser->user, (const XML_Char *) full_pi, xmlStrlen(full_pi));
286+
parser->h_default(parser->user, (const XML_Char *) full_pi, strlen(full_pi));
216287
efree(full_pi);
217288
}
218289
return;

ext/xml/tests/bug46699.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Bug #46699: (xml_parse crash when parser is namespace aware)
3+
--SKIPIF--
4+
<?php
5+
require_once("skipif.inc");
6+
if (! @xml_parser_create_ns('ISO-8859-1')) { die("skip xml_parser_create_ns is not supported on this platform");}
7+
?>
8+
--FILE--
9+
<?php
10+
function defaultfunc($parser, $data)
11+
{
12+
echo $data;
13+
}
14+
15+
$xml = <<<HERE
16+
<a xmlns="http://example.com/foo"
17+
xmlns:bar="http://example.com/bar">
18+
<bar:b foo="bar">1</bar:b>
19+
<bar:c bar:nix="null" foo="bar">2</bar:c>
20+
</a>
21+
HERE;
22+
23+
$parser = xml_parser_create_ns("ISO-8859-1","@");
24+
xml_set_default_handler($parser,'defaultfunc');
25+
xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
26+
xml_parse($parser, $xml);
27+
xml_parser_free($parser);
28+
?>
29+
--EXPECT--
30+
<a xmlns="http://example.com/foo" xmlns:bar="http://example.com/bar">
31+
<bar:b foo="bar">1</bar:b>
32+
<bar:c bar:nix="null" foo="bar">2</bar:c>
33+
</a>

0 commit comments

Comments
 (0)