Skip to content

Commit 5c039bb

Browse files
committed
Fixed for Bug #26384 (domxslt->process causes segfault with xsl:key)
1 parent e57b75e commit 5c039bb

File tree

3 files changed

+49
-18
lines changed

3 files changed

+49
-18
lines changed

ext/xsl/php_xsl.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
113113
intern->ptr = NULL;
114114
intern->prop_handler = NULL;
115115
intern->parameter = NULL;
116+
intern->hasKeys = 0;
116117

117118
ALLOC_HASHTABLE(intern->std.properties);
118119
zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -145,6 +146,10 @@ PHP_MINIT_FUNCTION(xsl)
145146
xsltRegisterExtModuleFunction ((const xmlChar *) "function",
146147
(const xmlChar *) "http://php.net/xsl",
147148
xsl_ext_function_object_php);
149+
150+
REGISTER_LONG_CONSTANT("XSL_CLONE_AUTO", 0, CONST_CS | CONST_PERSISTENT);
151+
REGISTER_LONG_CONSTANT("XSL_CLONE_NEVER", -1, CONST_CS | CONST_PERSISTENT);
152+
REGISTER_LONG_CONSTANT("XSL_CLONE_ALWAYS", 1, CONST_CS | CONST_PERSISTENT);
148153

149154
return SUCCESS;
150155
}

ext/xsl/php_xsl.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ typedef struct _xsl_object {
5454
void *ptr;
5555
HashTable *prop_handler;
5656
zend_object_handle handle;
57-
HashTable *parameter;
57+
HashTable *parameter;
58+
int hasKeys;
5859
} xsl_object;
5960

6061
void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC);
@@ -72,8 +73,8 @@ entry = zend_register_internal_class_ex(&ce, parent_ce, NULL TSRMLS_CC);
7273
RETURN_FALSE; \
7374
}
7475

75-
76-
76+
77+
7778
PHP_MINIT_FUNCTION(xsl);
7879
PHP_MSHUTDOWN_FUNCTION(xsl);
7980
PHP_RINIT_FUNCTION(xsl);

ext/xsl/xsltprocessor.c

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,11 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
129129
xsltStylesheetPtr sheetp, oldsheetp;
130130
xsl_object *intern;
131131
php_libxml_node_object *docobj;
132-
int prevSubstValue, prevExtDtdValue;
133-
132+
int prevSubstValue, prevExtDtdValue, clone_docu;
133+
xmlNode *nodep;
134+
zend_object_handlers *std_hnd;
135+
zval *cloneDocu, *member;
136+
134137
DOM_GET_THIS(id);
135138

136139
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
@@ -143,10 +146,10 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
143146
stylesheet document otherwise the node proxies will be a mess */
144147
newdoc = xmlCopyDoc(doc, 1);
145148
xmlNodeSetBase((xmlNodePtr) newdoc, (xmlChar *)doc->URL);
146-
147149
prevSubstValue = xmlSubstituteEntitiesDefault(1);
148150
prevExtDtdValue = xmlLoadExtDtdDefaultValue;
149151
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
152+
150153
sheetp = xsltParseStylesheetDoc(newdoc);
151154
xmlSubstituteEntitiesDefault(prevSubstValue);
152155
xmlLoadExtDtdDefaultValue = prevExtDtdValue;
@@ -157,6 +160,28 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
157160
}
158161

159162
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
163+
164+
std_hnd = zend_get_std_object_handlers();
165+
MAKE_STD_ZVAL(member);
166+
ZVAL_STRING(member, "cloneDocument", 0);
167+
cloneDocu = std_hnd->read_property(id, member, 1 TSRMLS_CC);
168+
convert_to_long(cloneDocu);
169+
efree(member);
170+
clone_docu = Z_LVAL_P(cloneDocu);
171+
if (clone_docu == 0) {
172+
/* check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation */
173+
nodep = xmlDocGetRootElement(sheetp->doc)->children;
174+
while (nodep) {
175+
if (nodep->type == XML_ELEMENT_NODE && xmlStrEqual(nodep->name, "key") && xmlStrEqual(nodep->ns->href, XSLT_NAMESPACE)) {
176+
intern->hasKeys = 1;
177+
break;
178+
}
179+
nodep = nodep->next;
180+
}
181+
} else {
182+
intern->hasKeys = clone_docu;
183+
}
184+
160185
if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) {
161186
/* free wrapper */
162187
if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) {
@@ -181,7 +206,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
181206
xmlDoc *doc = NULL;
182207
xmlDoc *newdocp;
183208
xsltStylesheetPtr sheetp;
184-
int ret, clone = 0;
209+
int ret, clone;
185210
char **params = NULL;
186211
xsl_object *intern;
187212
php_libxml_node_object *docobj;
@@ -190,7 +215,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
190215
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
191216
sheetp = (xsltStylesheetPtr) intern->ptr;
192217

193-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|l", &docp, &clone) == FAILURE) {
218+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
194219
RETURN_FALSE;
195220
}
196221
DOC_GET_OBJ(doc, docp, xmlDocPtr, docobj);
@@ -199,11 +224,11 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc)
199224
params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
200225
}
201226

202-
if (clone == 1) {
227+
if (intern->hasKeys == 1) {
203228
doc = xmlCopyDoc(doc, 1);
204229
}
205230
newdocp = xsltApplyStylesheet(sheetp, doc, (const char**) params);
206-
if (clone == 1) {
231+
if (intern->hasKeys == 1) {
207232
xmlFreeDoc(doc);
208233
}
209234

@@ -233,7 +258,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
233258
xmlDoc *doc = NULL;
234259
xmlDoc *newdocp;
235260
xsltStylesheetPtr sheetp;
236-
int ret, uri_len, clone = 0;
261+
int ret, uri_len, clone;
237262
char **params = NULL, *uri;
238263
xsl_object *intern;
239264
php_libxml_node_object *docobj;
@@ -242,7 +267,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
242267
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
243268
sheetp = (xsltStylesheetPtr) intern->ptr;
244269

245-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os|l", &docp, &uri, &uri_len, &clone) == FAILURE) {
270+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os", &docp, &uri, &uri_len) == FAILURE) {
246271
RETURN_FALSE;
247272
}
248273

@@ -252,13 +277,13 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri)
252277
params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
253278
}
254279

255-
if (clone == 1) {
280+
if (intern->hasKeys == 1) {
256281
doc = xmlCopyDoc(doc, 1);
257282
}
258283

259284
newdocp = xsltApplyStylesheet(sheetp, doc, (const char**)params);
260285

261-
if (clone == 1) {
286+
if (intern->hasKeys == 1) {
262287
xmlFreeDoc(doc);
263288
}
264289

@@ -289,7 +314,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
289314
xmlDoc *doc = NULL;
290315
xmlDoc *newdocp;
291316
xsltStylesheetPtr sheetp;
292-
int ret, clone = 0;
317+
int ret, clone;
293318
xmlChar *doc_txt_ptr;
294319
int doc_txt_len;
295320
char **params = NULL;
@@ -300,7 +325,7 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
300325
intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC);
301326
sheetp = (xsltStylesheetPtr) intern->ptr;
302327

303-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|l", &docp, &clone) == FAILURE) {
328+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
304329
RETURN_FALSE;
305330
}
306331
DOC_GET_OBJ(doc, docp, xmlDocPtr, docobj);
@@ -309,13 +334,13 @@ PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml)
309334
params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC);
310335
}
311336

312-
if (clone == 1) {
337+
if (intern->hasKeys == 1) {
313338
doc = xmlCopyDoc(doc, 1);
314339
}
315340

316341
newdocp = xsltApplyStylesheet(sheetp, doc, (const char**)params);
317342

318-
if (clone == 1) {
343+
if (intern->hasKeys == 1) {
319344
xmlFreeDoc(doc);
320345
}
321346

0 commit comments

Comments
 (0)