Browse Source

Fix bug #27436 dom_import_simplexml innaccurate

extensions register callbacks to export nodes
prevents segfault passing invalid objects to import functions
PEAR_1_4DEV
Rob Richards 23 years ago
parent
commit
76ee5707f7
  1. 23
      ext/dom/php_dom.c
  2. 42
      ext/libxml/libxml.c
  3. 4
      ext/libxml/php_libxml.h
  4. 17
      ext/simplexml/simplexml.c
  5. 17
      ext/xsl/xsltprocessor.c

23
ext/dom/php_dom.c

@ -277,6 +277,20 @@ void dom_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
}
/* }}} */
void *php_dom_export_node(zval *object TSRMLS_DC)
{
php_libxml_node_object *intern;
xmlNodePtr nodep = NULL;
intern = (php_libxml_node_object *)zend_object_store_get_object(object TSRMLS_CC);
if (intern && intern->node) {
nodep = intern->node->node;
}
return nodep;
}
/* {{{ proto somNode dom_import_simplexml(sxeobject node)
Get a simplexml_element object from dom to allow for processing */
PHP_FUNCTION(dom_import_simplexml)
@ -284,7 +298,7 @@ PHP_FUNCTION(dom_import_simplexml)
#ifdef HAVE_SIMPLEXML
zval *rv = NULL;
zval *node;
xmlNodePtr nodep;
xmlNodePtr nodep = NULL;
php_libxml_node_object *nodeobj;
int ret;
@ -292,9 +306,10 @@ PHP_FUNCTION(dom_import_simplexml)
return;
}
NODE_GET_OBJ(nodep, node, xmlNodePtr, nodeobj);
nodeobj = (php_libxml_node_object *)zend_object_store_get_object(node TSRMLS_CC);
nodep = php_libxml_import_node(node TSRMLS_CC);
if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE) {
if (nodep && nodeobj && (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE)) {
DOM_RET_OBJ(rv, (xmlNodePtr) nodep, &ret, (dom_object *)nodeobj);
} else {
php_error(E_WARNING, "Invalid Nodetype to import");
@ -627,6 +642,8 @@ PHP_MINIT_FUNCTION(dom)
REGISTER_LONG_CONSTANT("DOM_INVALID_ACCESS_ERR", INVALID_ACCESS_ERR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("DOM_VALIDATION_ERR", VALIDATION_ERR, CONST_CS | CONST_PERSISTENT);
php_libxml_register_export(dom_node_class_entry, php_dom_export_node);
return SUCCESS;
}
/* }}} */

42
ext/libxml/libxml.c

@ -50,6 +50,12 @@
/* a true global for initialization */
int _php_libxml_initialized = 0;
typedef struct _php_libxml_func_handler {
php_libxml_export_node export_func;
} php_libxml_func_handler;
static HashTable php_libxml_exports;
#ifdef ZTS
int libxml_globals_id;
#else
@ -397,6 +403,8 @@ PHP_LIBXML_API void php_libxml_initialize() {
/* report errors via handler rather than stderr */
xmlSetGenericErrorFunc(NULL, php_libxml_error_handler);
zend_hash_init(&php_libxml_exports, 0, NULL, NULL, 1);
_php_libxml_initialized = 1;
}
}
@ -406,6 +414,7 @@ PHP_LIBXML_API void php_libxml_shutdown() {
/* reset libxml generic error handling */
xmlSetGenericErrorFunc(NULL, NULL);
xmlCleanupParser();
zend_hash_destroy(&php_libxml_exports);
_php_libxml_initialized = 0;
}
}
@ -434,6 +443,7 @@ PHP_RINIT_FUNCTION(libxml)
PHP_MSHUTDOWN_FUNCTION(libxml)
{
php_libxml_shutdown();
return SUCCESS;
}
@ -474,7 +484,39 @@ PHP_FUNCTION(libxml_set_streams_context)
}
/* }}} */
/* {{{ Common functions shared by extensions */
int php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function)
{
php_libxml_func_handler export_hnd;
/* Initialize in case this module hasnt been loaded yet */
php_libxml_initialize();
export_hnd.export_func = export_function;
return zend_hash_add(&php_libxml_exports, ce->name, ce->name_length + 1, &export_hnd, sizeof(export_hnd), NULL);
}
PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object TSRMLS_DC)
{
zend_class_entry *ce = NULL;
xmlNodePtr node = NULL;
php_libxml_func_handler *export_hnd;
if (object->type == IS_OBJECT) {
ce = Z_OBJCE_P(object);
while (ce->parent != NULL) {
ce = ce->parent;
}
if (zend_hash_find(&php_libxml_exports, ce->name, ce->name_length + 1, (void **) &export_hnd) == SUCCESS) {
node = export_hnd->export_func(object TSRMLS_CC);
}
}
return node;
}
int php_libxml_increment_node_ptr(php_libxml_node_object *object, xmlNodePtr node, void *private_data TSRMLS_DC)
{
int ret_refcount = -1;

4
ext/libxml/php_libxml.h

@ -64,11 +64,15 @@ typedef struct _php_libxml_node_object {
HashTable *properties;
} php_libxml_node_object;
typedef void * (*php_libxml_export_node) (zval *object TSRMLS_DC);
PHP_FUNCTION(libxml_set_streams_context);
int php_libxml_increment_node_ptr(php_libxml_node_object *object, xmlNodePtr node, void *private_data TSRMLS_DC);
int php_libxml_decrement_node_ptr(php_libxml_node_object *object TSRMLS_DC);
int php_libxml_increment_doc_ref(php_libxml_node_object *object, xmlDocPtr docp TSRMLS_DC);
int php_libxml_decrement_doc_ref(php_libxml_node_object *object TSRMLS_DC);
PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object TSRMLS_DC);
PHP_LIBXML_API int php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function);
/* When an explicit freeing of node and children is required */
void php_libxml_node_free_resource(xmlNodePtr node TSRMLS_DC);
/* When object dtor is called as node may still be referenced */

17
ext/simplexml/simplexml.c

@ -1490,6 +1490,16 @@ static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC)
}
void *simplexml_export_node(zval *object TSRMLS_DC)
{
php_sxe_object *sxe;
xmlNodePtr node;
sxe = php_sxe_fetch_object(object TSRMLS_CC);
GET_NODE(sxe, node);
return php_sxe_get_first_node(sxe, node TSRMLS_CC);
}
#ifdef HAVE_DOM
/* {{{ proto simplemxml_element simplexml_import_dom(domNode node [, string class_name])
Get a simplexml_element object from dom to allow for processing */
@ -1509,8 +1519,9 @@ PHP_FUNCTION(simplexml_import_dom)
object = (php_libxml_node_object *)zend_object_store_get_object(node TSRMLS_CC);
if (object->node && object->node->node) {
nodep = object->node->node;
nodep = php_libxml_import_node(node TSRMLS_CC);
if (nodep) {
if (nodep->doc == NULL) {
php_error(E_WARNING, "Imported Node must have associated Document");
RETURN_NULL();
@ -1603,6 +1614,8 @@ PHP_MINIT_FUNCTION(simplexml)
}
#endif /* HAVE_SPL */
php_libxml_register_export(sxe_class_entry, simplexml_export_node);
return SUCCESS;
}
/* }}} */

17
ext/xsl/xsltprocessor.c

@ -296,19 +296,24 @@ PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet)
xmlDoc *doc = NULL, *newdoc = NULL;
xsltStylesheetPtr sheetp, oldsheetp;
xsl_object *intern;
php_libxml_node_object *docobj;
int prevSubstValue, prevExtDtdValue, clone_docu = 0;
xmlNode *nodep;
xmlNode *nodep = NULL;
zend_object_handlers *std_hnd;
zval *cloneDocu, *member;
DOM_GET_THIS(id);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) {
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo", &id, xsl_xsltprocessor_class_entry, &docp) == FAILURE) {
RETURN_FALSE;
}
DOC_GET_OBJ(doc, docp, xmlDocPtr, docobj);
nodep = php_libxml_import_node(docp TSRMLS_CC);
if (nodep) {
doc = nodep->doc;
}
if (doc == NULL) {
php_error(E_WARNING, "Invalid Document");
RETURN_NULL();
}
/* libxslt uses _private, so we must copy the imported
stylesheet document otherwise the node proxies will be a mess */

Loading…
Cancel
Save