diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index c30145d9fb940..ed4ad2516f43b 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -703,11 +703,6 @@ PHP_METHOD(Phar, webPhar) goto cleanup_fail; } - if (Z_TYPE_P(rewrite_fci.retval) == IS_UNDEF || Z_TYPE(retval) == IS_UNDEF) { - zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false"); - goto cleanup_fail; - } - switch (Z_TYPE(retval)) { case IS_STRING: efree(entry); @@ -3174,12 +3169,14 @@ static int phar_test_compression(zval *zv, void *argument) /* {{{ */ if (!PHAR_G(has_bz2)) { if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) { *(int *) argument = 0; + return ZEND_HASH_APPLY_STOP; } } if (!PHAR_G(has_zlib)) { if (entry->flags & PHAR_ENT_COMPRESSED_GZ) { *(int *) argument = 0; + return ZEND_HASH_APPLY_STOP; } } @@ -4518,28 +4515,27 @@ PHP_METHOD(PharFileInfo, __construct) } /* }}} */ -#define PHAR_ENTRY_OBJECT() \ +#define PHAR_ENTRY_OBJECT_EX(throw) \ zval *zobj = ZEND_THIS; \ phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \ if (!entry_obj->entry) { \ - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \ - "Cannot call method on an uninitialized PharFileInfo object"); \ - RETURN_THROWS(); \ + if (throw) { \ + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \ + "Cannot call method on an uninitialized PharFileInfo object"); \ + } \ + return; \ } +#define PHAR_ENTRY_OBJECT() PHAR_ENTRY_OBJECT_EX(true) + /* {{{ clean up directory-based entry objects */ PHP_METHOD(PharFileInfo, __destruct) { - zval *zobj = ZEND_THIS; - phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); - if (zend_parse_parameters_none() == FAILURE) { RETURN_THROWS(); } - if (!entry_obj->entry) { - return; - } + PHAR_ENTRY_OBJECT_EX(false); if (entry_obj->entry->is_temp_dir) { if (entry_obj->entry->filename) { diff --git a/ext/phar/zip.c b/ext/phar/zip.c index ca536c9c75aae..2d43092e97ae7 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -641,13 +641,6 @@ int phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, char *alia zend_off_t restore_pos = php_stream_tell(fp); php_stream_seek(fp, entry.offset, SEEK_SET); - /* these next lines should be for php < 5.2.6 after 5.3 filters are fixed */ - fp->writepos = 0; - fp->readpos = 0; - php_stream_seek(fp, entry.offset, SEEK_SET); - fp->writepos = 0; - fp->readpos = 0; - /* the above lines should be for php < 5.2.6 after 5.3 filters are fixed */ mydata->alias_len = entry.uncompressed_filesize; if (entry.flags & PHAR_ENT_COMPRESSED_GZ) { diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index 254fbde7b3ff0..5d36266393b04 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -1257,6 +1257,10 @@ PHP_METHOD(SplHeap, __unserialize) Z_PARAM_ARRAY_HT(data) ZEND_PARSE_PARAMETERS_END(); + if (UNEXPECTED(spl_heap_consistency_validations(intern, true) != SUCCESS)) { + RETURN_THROWS(); + } + if (zend_hash_num_elements(data) != 2) { zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(intern->std.ce->name)); RETURN_THROWS(); @@ -1285,10 +1289,6 @@ PHP_METHOD(SplHeap, __unserialize) RETURN_THROWS(); } - if (EG(exception)) { - RETURN_THROWS(); - } - if (UNEXPECTED(spl_heap_consistency_validations(intern, false) != SUCCESS)) { RETURN_THROWS(); } diff --git a/ext/spl/tests/heap_unserialize_under_corruption_or_modification.phpt b/ext/spl/tests/heap_unserialize_under_corruption_or_modification.phpt new file mode 100644 index 0000000000000..2e54be09ad1a7 --- /dev/null +++ b/ext/spl/tests/heap_unserialize_under_corruption_or_modification.phpt @@ -0,0 +1,30 @@ +--TEST-- +SplHeap should not accept unserialize data when it is corrupted or under modification +--FILE-- +__unserialize($array); + return $a < $b ? -1 : ($a == $b ? 0 : 1); + } +} + +$heap = new SplMaxHeap; +$heap->insert(1); +$array = $heap->__serialize(); + +$heap = new MyHeap; +$heap->insert(0); +try { + $heap->insert(2); +} catch (RuntimeException $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Heap cannot be changed when it is already being modified. diff --git a/ext/xml/compat.c b/ext/xml/compat.c index 21184be87182b..6ce0809cd5b09 100644 --- a/ext/xml/compat.c +++ b/ext/xml/compat.c @@ -18,19 +18,22 @@ #if defined(HAVE_LIBXML) && (defined(HAVE_XML) || defined(HAVE_XMLRPC)) && !defined(HAVE_LIBEXPAT) #include "expat_compat.h" #include "ext/libxml/php_libxml.h" +#include "Zend/zend_smart_string.h" #ifdef LIBXML_EXPAT_COMPAT -static void -qualify_namespace(XML_Parser parser, const xmlChar *name, const xmlChar *URI, xmlChar **qualified) +static xmlChar * +qualify_namespace(XML_Parser parser, const xmlChar *name, const xmlChar *URI) { if (URI) { - /* Use libxml functions otherwise its memory deallocation is screwed up */ - *qualified = xmlStrdup(URI); - *qualified = xmlStrncat(*qualified, parser->_ns_separator, 1); - *qualified = xmlStrncat(*qualified, name, xmlStrlen(name)); + smart_string str = {0}; + smart_string_appends(&str, (const char *) URI); + smart_string_appends(&str, (const char *) parser->_ns_separator); + smart_string_appends(&str, (const char *) name); + smart_string_0(&str); + return BAD_CAST str.c; } else { - *qualified = xmlStrdup(name); + return BAD_CAST estrdup((const char *) name); } } @@ -38,31 +41,31 @@ static void start_element_handler(void *user, const xmlChar *name, const xmlChar **attributes) { XML_Parser parser = (XML_Parser) user; - xmlChar *qualified_name = NULL; if (parser->h_start_element == NULL) { if (parser->h_default) { int attno = 0; + smart_string qualified_name = {0}; + + smart_string_appendc(&qualified_name, '<'); + smart_string_appends(&qualified_name, (const char *) name); - qualified_name = xmlStrncatNew((xmlChar *)"<", name, xmlStrlen(name)); if (attributes) { while (attributes[attno] != NULL) { - int att_len; - char *att_string, *att_name, *att_value; - - att_name = (char *)attributes[attno++]; - att_value = (char *)attributes[attno++]; - - att_len = spprintf(&att_string, 0, " %s=\"%s\"", att_name, att_value); - - qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_string, att_len); - efree(att_string); + const char *att_name = (const char *) attributes[attno++]; + const char *att_value = (const char *) attributes[attno++]; + + smart_string_appendc(&qualified_name, ' '); + smart_string_appends(&qualified_name, att_name); + smart_string_appends(&qualified_name, "=\""); + smart_string_appends(&qualified_name, att_value); + smart_string_appendc(&qualified_name, '"'); } - } - qualified_name = xmlStrncat(qualified_name, (xmlChar *)">", 1); - parser->h_default(parser->user, (const XML_Char *) qualified_name, xmlStrlen(qualified_name)); - xmlFree(qualified_name); + smart_string_appendc(&qualified_name, '>'); + smart_string_0(&qualified_name); + parser->h_default(parser->user, (const XML_Char *) qualified_name.c, qualified_name.len); + smart_string_free(&qualified_name); } return; } @@ -90,67 +93,61 @@ start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix, if (parser->h_start_element == NULL) { if (parser->h_default) { - + smart_string qualified_name = {0}; + smart_string_appendc(&qualified_name, '<'); if (prefix) { - qualified_name = xmlStrncatNew((xmlChar *)"<", prefix, xmlStrlen(prefix)); - qualified_name = xmlStrncat(qualified_name, (xmlChar *)":", 1); - qualified_name = xmlStrncat(qualified_name, name, xmlStrlen(name)); - } else { - qualified_name = xmlStrncatNew((xmlChar *)"<", name, xmlStrlen(name)); + smart_string_appends(&qualified_name, (const char *) prefix); + smart_string_appendc(&qualified_name, ':'); } + smart_string_appends(&qualified_name, (const char *) name); if (namespaces) { int i, j; for (i = 0,j = 0;j < nb_namespaces;j++) { - int ns_len; - char *ns_string, *ns_prefix, *ns_url; - - ns_prefix = (char *) namespaces[i++]; - ns_url = (char *) namespaces[i++]; + const char *ns_prefix = (const char *) namespaces[i++]; + const char *ns_url = (const char *) namespaces[i++]; if (ns_prefix) { - ns_len = spprintf(&ns_string, 0, " xmlns:%s=\"%s\"", ns_prefix, ns_url); + smart_string_appends(&qualified_name, " xmlns:"); + smart_string_appends(&qualified_name, ns_prefix); + smart_string_appends(&qualified_name, "=\""); } else { - ns_len = spprintf(&ns_string, 0, " xmlns=\"%s\"", ns_url); + smart_string_appends(&qualified_name, " xmlns=\""); } - qualified_name = xmlStrncat(qualified_name, (xmlChar *)ns_string, ns_len); - efree(ns_string); + smart_string_appends(&qualified_name, ns_url); + smart_string_appendc(&qualified_name, '"'); } } if (attributes) { for (i = 0; i < nb_attributes; i += 1) { - int att_len; - char *att_string, *att_name, *att_value, *att_prefix, *att_valueend; - - att_name = (char *) attributes[y++]; - att_prefix = (char *)attributes[y++]; + const char *att_name = (const char *) attributes[y++]; + const char *att_prefix = (const char *)attributes[y++]; y++; - att_value = (char *)attributes[y++]; - att_valueend = (char *)attributes[y++]; + const char *att_value = (const char *)attributes[y++]; + const char *att_valueend = (const char *)attributes[y++]; + smart_string_appendc(&qualified_name, ' '); if (att_prefix) { - att_len = spprintf(&att_string, 0, " %s:%s=\"", att_prefix, att_name); - } else { - att_len = spprintf(&att_string, 0, " %s=\"", att_name); + smart_string_appends(&qualified_name, att_prefix); + smart_string_appendc(&qualified_name, ':'); } + smart_string_appends(&qualified_name, att_name); + smart_string_appends(&qualified_name, "=\""); - qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_string, att_len); - qualified_name = xmlStrncat(qualified_name, (xmlChar *)att_value, att_valueend - att_value); - qualified_name = xmlStrncat(qualified_name, (xmlChar *)"\"", 1); - - efree(att_string); + smart_string_appendl(&qualified_name, att_value, att_valueend - att_value); + smart_string_appendc(&qualified_name, '"'); } } - qualified_name = xmlStrncat(qualified_name, (xmlChar *)">", 1); - parser->h_default(parser->user, (const XML_Char *) qualified_name, xmlStrlen(qualified_name)); - xmlFree(qualified_name); + smart_string_appendc(&qualified_name, '>'); + parser->h_default(parser->user, (const XML_Char *) qualified_name.c, qualified_name.len); + smart_string_free(&qualified_name); } return; } - qualify_namespace(parser, name, URI, &qualified_name); + qualified_name = qualify_namespace(parser, name, URI); if (attributes != NULL) { xmlChar *qualified_name_attr = NULL; @@ -159,12 +156,12 @@ start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix, for (i = 0; i < nb_attributes; i += 1) { if (attributes[y+1] != NULL) { - qualify_namespace(parser, attributes[y] , attributes[y + 2], &qualified_name_attr); + qualified_name_attr = qualify_namespace(parser, attributes[y] , attributes[y + 2]); } else { - qualified_name_attr = xmlStrdup(attributes[y]); + qualified_name_attr = BAD_CAST estrdup((const char *) attributes[y]); } attrs[z] = qualified_name_attr; - attrs[z + 1] = xmlStrndup(attributes[y + 3] , (int) (attributes[y + 4] - attributes[y + 3])); + attrs[z + 1] = BAD_CAST estrndup((const char *) attributes[y + 3], attributes[y + 4] - attributes[y + 3]); z += 2; y += 5; } @@ -174,11 +171,11 @@ start_element_handler_ns(void *user, const xmlChar *name, const xmlChar *prefix, parser->h_start_element(parser->user, (const XML_Char *) qualified_name, (const XML_Char **) attrs); if (attrs) { for (i = 0; i < z; i++) { - xmlFree(attrs[i]); + efree(attrs[i]); } efree(attrs); } - xmlFree(qualified_name); + efree(qualified_name); } static void @@ -222,11 +219,11 @@ end_element_handler_ns(void *user, const xmlChar *name, const xmlChar * prefix, return; } - qualify_namespace(parser, name, URI, &qualified_name); + qualified_name = qualify_namespace(parser, name, URI); parser->h_end_element(parser->user, (const XML_Char *) qualified_name); - xmlFree(qualified_name); + efree(qualified_name); } static void @@ -290,17 +287,19 @@ notation_decl_handler(void *user, const xmlChar *notation, const xmlChar *pub_id parser->h_notation_decl(parser->user, notation, NULL, sys_id, pub_id); } -static void -build_comment(const xmlChar *data, size_t data_len, xmlChar **comment, size_t *comment_len) +static xmlChar * +build_comment(const xmlChar *data, size_t data_len, size_t *comment_len) { *comment_len = data_len + 7; - *comment = xmlMalloc(*comment_len + 1); - memcpy(*comment, "", 3); + xmlChar *comment = emalloc(*comment_len + 1); + memcpy(comment, "", 3); - (*comment)[*comment_len] = '\0'; + comment[*comment_len] = '\0'; + + return comment; } static void @@ -309,24 +308,24 @@ comment_handler(void *user, const xmlChar *comment) XML_Parser parser = (XML_Parser) user; if (parser->h_default) { - xmlChar *d_comment; size_t d_comment_len; - build_comment(comment, (size_t) xmlStrlen(comment), &d_comment, &d_comment_len); + xmlChar *d_comment = build_comment(comment, (size_t) xmlStrlen(comment), &d_comment_len); parser->h_default(parser->user, d_comment, d_comment_len); - xmlFree(d_comment); + efree(d_comment); } } -static void -build_entity(const xmlChar *name, size_t len, xmlChar **entity, size_t *entity_len) +static xmlChar * +build_entity(const xmlChar *name, size_t len, size_t *entity_len) { *entity_len = len + 2; - *entity = xmlMalloc(*entity_len + 1); - (*entity)[0] = '&'; - memcpy(*entity+1, name, len); - (*entity)[len+1] = ';'; - (*entity)[*entity_len] = '\0'; + xmlChar *entity = emalloc(*entity_len + 1); + entity[0] = '&'; + memcpy(entity + 1, name, len); + entity[len + 1] = ';'; + entity[*entity_len] = '\0'; + return entity; } static void @@ -361,12 +360,11 @@ get_entity(void *user, const xmlChar *name) if (ret == NULL || ret->etype == XML_INTERNAL_GENERAL_ENTITY || ret->etype == XML_INTERNAL_PARAMETER_ENTITY || ret->etype == XML_INTERNAL_PREDEFINED_ENTITY) { /* Predefined entities will expand unless no cdata handler is present */ if (parser->h_default && ! (ret && ret->etype == XML_INTERNAL_PREDEFINED_ENTITY && parser->h_cdata)) { - xmlChar *entity; size_t len; - build_entity(name, (size_t) xmlStrlen(name), &entity, &len); + xmlChar *entity = build_entity(name, (size_t) xmlStrlen(name), &len); parser->h_default(parser->user, (const xmlChar *) entity, len); - xmlFree(entity); + efree(entity); } else { /* expat will not expand internal entities if default handler is present otherwise it will expand and pass them to cdata handler */ @@ -464,7 +462,7 @@ XML_ParserCreate_MM(const XML_Char *encoding, const XML_Memory_Handling_Suite *m /* Note: sax2 flag will be set due to the magic number in `initialized` in php_xml_compat_handlers */ ZEND_ASSERT(parser->parser->sax->initialized == XML_SAX2_MAGIC); parser->use_namespace = 1; - parser->_ns_separator = xmlStrdup(sep); + parser->_ns_separator = BAD_CAST estrdup((const char *) sep); } else { /* Reset flag as XML_SAX2_MAGIC is needed for xmlCreatePushParserCtxt so must be set in the handlers */ @@ -717,7 +715,7 @@ XML_ParserFree(XML_Parser parser) { if (parser->use_namespace) { if (parser->_ns_separator) { - xmlFree(parser->_ns_separator); + efree(parser->_ns_separator); } } if (parser->parser->myDoc) { diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index 271c839eb65a4..d379b6dfad99b 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -517,12 +517,7 @@ static void php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAMETERS, xmlreader_ /* {{{ php_xmlreader_set_relaxng_schema */ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int type) { -#ifdef LIBXML_SCHEMAS_ENABLED - zval *id; size_t source_len = 0; - int retval = -1; - xmlreader_object *intern; - xmlRelaxNGPtr schema = NULL; char *source; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &source, &source_len) == FAILURE) { @@ -533,11 +528,13 @@ static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int t zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } - - id = ZEND_THIS; - - intern = Z_XMLREADER_P(id); + +#ifdef LIBXML_SCHEMAS_ENABLED + xmlreader_object *intern = Z_XMLREADER_P(ZEND_THIS); if (intern->ptr) { + int retval = -1; + xmlRelaxNGPtr schema = NULL; + if (source) { schema = _xmlreader_get_relaxNG(source, source_len, type, NULL, NULL); if (schema) { @@ -1079,11 +1076,7 @@ PHP_METHOD(XMLReader, readString) /* {{{ Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read(). */ PHP_METHOD(XMLReader, setSchema) { -#ifdef LIBXML_SCHEMAS_ENABLED - zval *id; size_t source_len = 0; - int retval = -1; - xmlreader_object *intern; char *source; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &source, &source_len) == FAILURE) { @@ -1094,13 +1087,12 @@ PHP_METHOD(XMLReader, setSchema) zend_argument_must_not_be_empty_error(1); RETURN_THROWS(); } - - id = ZEND_THIS; - - intern = Z_XMLREADER_P(id); + +#ifdef LIBXML_SCHEMAS_ENABLED + xmlreader_object *intern = Z_XMLREADER_P(ZEND_THIS); if (intern && intern->ptr) { PHP_LIBXML_SANITIZE_GLOBALS(schema); - retval = xmlTextReaderSchemaValidate(intern->ptr, source); + int retval = xmlTextReaderSchemaValidate(intern->ptr, source); PHP_LIBXML_RESTORE_GLOBALS(schema); if (retval == 0) {