From 19866fb76cf4c95d904ebb0e08592cf38303fae9 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Thu, 1 Sep 2016 23:15:34 -0700 Subject: Fix various int size overflows. Add function for detection of string zvals with length that does not fit INT_MAX. --- Zend/zend_API.c | 61 ++++++++++++++--- Zend/zend_API.h | 14 ++++ Zend/zend_alloc.c | 9 +++ Zend/zend_alloc.h | 4 +- ext/imap/php_imap.c | 28 +++++--- ext/ldap/ldap.c | 2 +- ext/pcre/php_pcre.c | 14 ++-- ext/pgsql/pgsql.c | 186 +++++++++++++++++++++++++------------------------- ext/standard/string.c | 23 +++---- ext/xml/xml.c | 4 +- ext/zlib/zlib.c | 8 +-- 11 files changed, 210 insertions(+), 143 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 7e622c6ea7..1f50016bd6 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1074,7 +1074,7 @@ static int zval_update_class_constant(zval **pp, int is_static, int offset TSRML *scope = old_scope; return ret; } - } + } ce = ce->parent; } while (ce); @@ -1279,9 +1279,14 @@ ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, doubl ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */ { zval *tmp; + size_t _len = strlen(str); + + if (UNEXPECTED(_len > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } MAKE_STD_ZVAL(tmp); - ZVAL_STRING(tmp, str, duplicate); + ZVAL_STRINGL(tmp, str, _len, duplicate); return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); } @@ -1291,6 +1296,10 @@ ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char { zval *tmp; + if (UNEXPECTED(length > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } + MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); @@ -1362,6 +1371,11 @@ ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */ ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */ { zval *tmp; + size_t _len = strlen(str); + + if (UNEXPECTED(_len > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } MAKE_STD_ZVAL(tmp); ZVAL_STRING(tmp, str, duplicate); @@ -1374,6 +1388,10 @@ ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint len { zval *tmp; + if (UNEXPECTED(length > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } + MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); @@ -1457,6 +1475,9 @@ ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int { zval *tmp; + if (UNEXPECTED(length > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); @@ -1473,9 +1494,14 @@ ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */ ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */ { zval *tmp; + size_t _len = strlen(str); + + if (UNEXPECTED(_len > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } MAKE_STD_ZVAL(tmp); - ZVAL_STRING(tmp, str, duplicate); + ZVAL_STRINGL(tmp, str, _len, duplicate); return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest); } @@ -1485,6 +1511,10 @@ ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, { zval *tmp; + if (UNEXPECTED(length > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } + MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); @@ -1664,9 +1694,14 @@ ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, co { zval *tmp; zval *z_key; + size_t _len = strlen(str); + + if (UNEXPECTED(_len > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } MAKE_STD_ZVAL(tmp); - ZVAL_STRING(tmp, str, duplicate); + ZVAL_STRINGL(tmp, str, _len, duplicate); MAKE_STD_ZVAL(z_key); ZVAL_STRINGL(z_key, key, key_len-1, 1); @@ -1683,6 +1718,10 @@ ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, c zval *tmp; zval *z_key; + if (UNEXPECTED(length > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String overflow, max size is %d", INT_MAX); + } + MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); @@ -1836,7 +1875,7 @@ ZEND_API void zend_collect_module_handlers(TSRMLS_D) /* {{{ */ module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1; module_post_deactivate_handlers[post_deactivate_count] = NULL; startup_count = 0; - + for (zend_hash_internal_pointer_reset_ex(&module_registry, &pos); zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) == SUCCESS; zend_hash_move_forward_ex(&module_registry, &pos)) { @@ -2083,7 +2122,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } if (ptr->arg_info) { zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info; - + internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1; internal_function->num_args = ptr->num_args; /* Currently you cannot denote that the function can accept less arguments than num_args */ @@ -2701,7 +2740,7 @@ static int zend_is_callable_check_class(const char *name, int name_len, zend_fca } ret = 1; } - } else if (name_len == sizeof("parent") - 1 && + } else if (name_len == sizeof("parent") - 1 && !memcmp(lcname, "parent", sizeof("parent") - 1)) { if (!EG(scope)) { if (error) *error = estrdup("cannot access parent:: when no class scope is active"); @@ -3030,7 +3069,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch if (error) { *error = NULL; } - + fcc->initialized = 0; fcc->calling_scope = NULL; fcc->called_scope = NULL; @@ -3042,7 +3081,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch object_ptr = NULL; } if (object_ptr && - (!EG(objects_store).object_buckets || + (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) { return 0; } @@ -3123,7 +3162,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch } } else { - if (!EG(objects_store).object_buckets || + if (!EG(objects_store).object_buckets || !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) { return 0; } @@ -3192,7 +3231,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint ch *callable_name = emalloc(*callable_name_len + 1); memcpy(*callable_name, ce->name, ce->name_length); memcpy((*callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke")); - } + } return 1; } /* break missing intentionally */ diff --git a/Zend/zend_API.h b/Zend/zend_API.h index e17be4ce68..3e191b63eb 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -654,6 +654,20 @@ END_EXTERN_C() } while (0) #define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; } +/* Check that returned string length fits int */ +#define RETVAL_STRINGL_CHECK(s, len, dup) \ + size_t __len = (len); \ + if (UNEXPECTED(__len > INT_MAX)) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, max is %d", INT_MAX); \ + if(!(dup)) { \ + efree((s)); \ + } \ + RETURN_FALSE; \ + } \ + RETVAL_STRINGL((s), __len, (dup)) + + + #define SET_VAR_STRING(n, v) { \ { \ zval *var; \ diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 105c2560aa..1f00414939 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2578,6 +2578,15 @@ static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) #endif +ZEND_API void *_safe_emalloc_string(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + size_t str_size = safe_address(nmemb, size, offset); + if (UNEXPECTED(str_size > INT_MAX)) { + zend_error_noreturn(E_ERROR, "String allocation overflow, max size is %d", INT_MAX); + } + return emalloc_rel(str_size); +} + ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { return emalloc_rel(safe_address(nmemb, size, offset)); diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 8169364cd3..719f9c5cae 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -5,7 +5,7 @@ | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | + | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -56,6 +56,7 @@ ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_M ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; +ZEND_API void *_safe_emalloc_string(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC; ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2); @@ -69,6 +70,7 @@ ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_ /* Standard wrapper macros */ #define emalloc(size) _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) #define safe_emalloc(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) +#define safe_emalloc_string(nmemb, size, offset) _safe_emalloc_string((nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) #define efree(ptr) _efree((ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) #define ecalloc(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) #define erealloc(ptr, size) _erealloc((ptr), (size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c index d5d3e2255a..8fe9de9ea8 100644 --- a/ext/imap/php_imap.c +++ b/ext/imap/php_imap.c @@ -1711,7 +1711,7 @@ PHP_FUNCTION(imap_body) if (body_len == 0) { RETVAL_EMPTY_STRING(); } else { - RETVAL_STRINGL(body, body_len, 1); + RETVAL_STRINGL_CHECK(body, body_len, 1); } } /* }}} */ @@ -1899,7 +1899,7 @@ PHP_FUNCTION(imap_list_full) } array_init(return_value); - delim = safe_emalloc(2, sizeof(char), 0); + delim = emalloc(2); cur=IMAPG(imap_folder_objects); while (cur != NIL) { MAKE_STD_ZVAL(mboxob); @@ -2205,7 +2205,7 @@ PHP_FUNCTION(imap_lsub_full) } array_init(return_value); - delim = safe_emalloc(2, sizeof(char), 0); + delim = emalloc(2); cur=IMAPG(imap_sfolder_objects); while (cur != NIL) { MAKE_STD_ZVAL(mboxob); @@ -2356,7 +2356,7 @@ PHP_FUNCTION(imap_fetchbody) php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body information available"); RETURN_FALSE; } - RETVAL_STRINGL(body, len, 1); + RETVAL_STRINGL_CHECK(body, len, 1); } /* }}} */ @@ -2396,7 +2396,12 @@ PHP_FUNCTION(imap_fetchmime) php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body MIME information available"); RETURN_FALSE; } - RETVAL_STRINGL(body, len, 1); + if (len > INT_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, max is %d", INT_MAX); + efree(body); + RETURN_FALSE; + } + RETVAL_STRINGL_CHECK(body, len, 1); } /* }}} */ @@ -2495,7 +2500,7 @@ PHP_FUNCTION(imap_qprint) RETURN_FALSE; } - RETVAL_STRINGL(decode, newlength, 1); + RETVAL_STRINGL_CHECK(decode, newlength, 1); fs_give((void**) &decode); } /* }}} */ @@ -2541,7 +2546,7 @@ PHP_FUNCTION(imap_binary) RETURN_FALSE; } - RETVAL_STRINGL(decode, newlength, 1); + RETVAL_STRINGL_CHECK(decode, newlength, 1); fs_give((void**) &decode); } /* }}} */ @@ -2626,7 +2631,7 @@ PHP_FUNCTION(imap_rfc822_write_address) string = _php_rfc822_write_address(addr TSRMLS_CC); if (string) { - RETVAL_STRING(string, 0); + RETVAL_STRINGL_CHECK(string, strlen(string), 0); } else { RETURN_FALSE; } @@ -2882,7 +2887,8 @@ PHP_FUNCTION(imap_utf7_encode) const unsigned char *in, *inp, *endp; unsigned char *out, *outp; unsigned char c; - int arg_len, inlen, outlen; + int arg_len, inlen; + size_t outlen; enum { ST_NORMAL, /* printable text */ ST_ENCODE0, /* encoded text rotation... */ @@ -2929,7 +2935,7 @@ PHP_FUNCTION(imap_utf7_encode) } /* allocate output buffer */ - out = emalloc(outlen + 1); + out = safe_emalloc_string(1, outlen, 1); /* encode input string */ outp = out; @@ -3019,7 +3025,7 @@ static void php_imap_mutf7(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */ if (out == NIL) { RETURN_FALSE; } else { - RETURN_STRING((char *)out, 1); + RETVAL_STRINGL_CHECK((char *)out, strlen(out), 1); } } /* }}} */ diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index e709e592fa..8ab0fe0727 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2647,7 +2647,7 @@ static void php_ldap_do_escape(const zend_bool *map, const char *value, size_t v len += (map[(unsigned char) value[i]]) ? 3 : 1; } - (*result) = (char *) safe_emalloc(1, len, 1); + (*result) = (char *) safe_emalloc_string(1, len, 1); (*resultlen) = len; for (i = 0; i < valuelen; i++) { diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 21ea01d92c..7589a7803c 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -806,7 +806,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec to achieve this, unless we're already at the end of the string. */ if (g_notempty != 0 && start_offset < subject_len) { int unit_len = calculate_unit_length(pce, subject + start_offset); - + offsets[0] = start_offset; offsets[1] = start_offset + unit_len; } else @@ -821,7 +821,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec the match again at the same point. If this fails (picked up above) we advance to the next character. */ g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0; - + /* Advance to the position right after the last full match */ start_offset = offsets[1]; } while (global); @@ -1055,7 +1055,7 @@ PHPAPI char *php_pcre_replace(char *regex, int regex_len, return NULL; } pce->refcount++; - result = php_pcre_replace_impl(pce, subject, subject_len, replace_val, + result = php_pcre_replace_impl(pce, subject, subject_len, replace_val, is_callable_replace, result_len, limit, replace_count TSRMLS_CC); pce->refcount--; @@ -1300,7 +1300,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub the match again at the same point. If this fails (picked up above) we advance to the next character. */ g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0; - + /* Advance to the next piece. */ start_offset = offsets[1]; } @@ -1593,7 +1593,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec #ifdef PCRE_EXTRA_MARK extra->flags &= ~PCRE_EXTRA_MARK; #endif - + /* Initialize return value */ array_init(return_value); @@ -1701,7 +1701,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec the match again at the same point. If this fails (picked up above) we advance to the next character. */ g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0; - + /* Advance to the position right after the last full match */ start_offset = offsets[1]; } @@ -1762,7 +1762,7 @@ static PHP_FUNCTION(preg_quote) /* Allocate enough memory so that even if each character is quoted, we won't run out of room */ - out_str = safe_emalloc(4, in_str_len, 1); + out_str = safe_emalloc_string(4, in_str_len, 1); /* Go through the string and quote necessary characters */ for(p = in_str, q = out_str; p != in_str_end; p++) { diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index f05efc7939..dfe8a7ddb2 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -959,7 +959,7 @@ static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) static void _php_pgsql_notice_handler(void *resource_id, const char *message) { php_pgsql_notice *notice; - + TSRMLS_FETCH(); if (! PGG(ignore_notices)) { notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice)); @@ -976,7 +976,7 @@ static void _php_pgsql_notice_handler(void *resource_id, const char *message) /* {{{ _php_pgsql_notice_dtor */ -static void _php_pgsql_notice_ptr_dtor(void **ptr) +static void _php_pgsql_notice_ptr_dtor(void **ptr) { php_pgsql_notice *notice = (php_pgsql_notice *)*ptr; if (notice) { @@ -995,7 +995,7 @@ static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC) PGresult *res; int orig; - if (Z_TYPE_P(rsrc) != le_plink) + if (Z_TYPE_P(rsrc) != le_plink) return 0; link = (PGconn *) rsrc->ptr; @@ -1004,7 +1004,7 @@ static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC) php_error_docref("ref.pgsql" TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode"); return -1; } - + while ((res = PQgetResult(link))) { PQclear(res); } @@ -1093,7 +1093,7 @@ static PHP_GINIT_FUNCTION(pgsql) { memset(pgsql_globals, 0, sizeof(zend_pgsql_globals)); /* Initilize notice message hash at MINIT only */ - zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, PHP_PGSQL_NOTICE_PTR_DTOR, 1, 0); + zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, PHP_PGSQL_NOTICE_PTR_DTOR, 1, 0); } /* }}} */ @@ -1283,11 +1283,11 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) } smart_str_appends(&str, "pgsql"); - + for (i = 0; i < ZEND_NUM_ARGS(); i++) { /* make sure that the PGSQL_CONNECT_FORCE_NEW bit is not part of the hash so that subsequent connections * can re-use this connection. Bug #39979 - */ + */ if (i == 1 && ZEND_NUM_ARGS() == 2 && Z_TYPE_PP(args[i]) == IS_LONG) { if (Z_LVAL_PP(args[1]) == PGSQL_CONNECT_FORCE_NEW) { continue; @@ -1325,11 +1325,11 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) if (persistent && PGG(allow_persistent)) { zend_rsrc_list_entry *le; - + /* try to find if we already have this link in our persistent list */ if (zend_hash_find(&EG(persistent_list), str.c, str.len+1, (void **) &le)==FAILURE) { /* we don't */ zend_rsrc_list_entry new_le; - + if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create new link. Too many open links (%ld)", PGG(num_links)); @@ -1483,7 +1483,7 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, (void*)Z_RESVAL_P(return_value)); } php_pgsql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC); - + cleanup: smart_str_free(&str); return; @@ -1550,7 +1550,7 @@ PHP_FUNCTION(pg_pconnect) /* }}} */ /* {{{ proto bool pg_close([resource connection]) - Close a PostgreSQL connection */ + Close a PostgreSQL connection */ PHP_FUNCTION(pg_close) { zval *pgsql_link = NULL; @@ -1608,12 +1608,12 @@ static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) { return; } - + if (argc == 0) { id = PGG(default_link); CHECK_DEFAULT_LINK(id); } - + if (pgsql_link == NULL && id == -1) { RETURN_FALSE; } @@ -1688,7 +1688,7 @@ static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type /* }}} */ /* {{{ proto string pg_dbname([resource connection]) - Get the database name */ + Get the database name */ PHP_FUNCTION(pg_dbname) { php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_DBNAME); @@ -1930,7 +1930,7 @@ PHP_FUNCTION(pg_query_params) PGresult *pgsql_result; ExecStatusType status; pgsql_result_handle *pg_result; - + if (argc == 2) { if (zend_parse_parameters(argc TSRMLS_CC, "sa", &query, &query_len, &pv_param_arr) == FAILURE) { return; @@ -1994,12 +1994,12 @@ PHP_FUNCTION(pg_query_params) } } - pgsql_result = PQexecParams(pgsql, query, num_params, + pgsql_result = PQexecParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0); if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) { PQclear(pgsql_result); PQreset(pgsql); - pgsql_result = PQexecParams(pgsql, query, num_params, + pgsql_result = PQexecParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0); } @@ -2008,7 +2008,7 @@ PHP_FUNCTION(pg_query_params) } else { status = (ExecStatusType) PQstatus(pgsql); } - + _php_pgsql_free_params(params, num_params); switch (status) { @@ -2201,12 +2201,12 @@ PHP_FUNCTION(pg_execute) } } - pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, + pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0); if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) { PQclear(pgsql_result); PQreset(pgsql); - pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, + pgsql_result = PQexecPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0); } @@ -2260,7 +2260,7 @@ static void php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_ty if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) { return; } - + ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; @@ -2315,13 +2315,13 @@ PHP_FUNCTION(pg_affected_rows) /* {{{ proto string pg_last_notice(resource connection) Returns the last notice set by the backend */ -PHP_FUNCTION(pg_last_notice) +PHP_FUNCTION(pg_last_notice) { zval *pgsql_link; PGconn *pg_link; int id = -1; php_pgsql_notice **notice; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) { return; } @@ -2372,7 +2372,7 @@ static char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list TSRMLS_DC) if ((tmp_oid = PQgetvalue(result,i,oid_offset))==NULL) { continue; } - + str.len = 0; smart_str_appends(&str, "pgsql_oid_"); smart_str_appends(&str, tmp_oid); @@ -2508,7 +2508,7 @@ static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_typ ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; - + if (field < 0 || field >= PQnfields(pgsql_result)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified"); RETURN_FALSE; @@ -2531,7 +2531,7 @@ static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_typ Z_TYPE_P(return_value) = IS_STRING; break; case PHP_PG_FIELD_TYPE_OID: - + oid = PQftype(pgsql_result, field); #if UINT_MAX > LONG_MAX if (oid > LONG_MAX) { @@ -2563,7 +2563,7 @@ PHP_FUNCTION(pg_field_name) /* }}} */ /* {{{ proto int pg_field_size(resource result, int field_number) - Returns the internal size of the field */ + Returns the internal size of the field */ PHP_FUNCTION(pg_field_size) { php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_SIZE); @@ -2629,7 +2629,7 @@ PHP_FUNCTION(pg_fetch_result) return; } } - + ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; @@ -2723,12 +2723,12 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type, php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type"); RETURN_FALSE; } - + ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; - if (use_row) { + if (use_row) { pgsql_row = row; pg_result->row = pgsql_row; if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) { @@ -2836,7 +2836,7 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type, /* }}} */ /* {{{ proto array pg_fetch_row(resource result [, int row [, int result_type]]) - Get a row as an enumerated array */ + Get a row as an enumerated array */ PHP_FUNCTION(pg_fetch_row) { php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM, 0); @@ -2931,7 +2931,7 @@ PHP_FUNCTION(pg_fetch_all_columns) if (PQgetisnull(pgsql_result, pg_row, colno)) { add_next_index_null(return_value); } else { - add_next_index_string(return_value, PQgetvalue(pgsql_result, pg_row, colno), 1); + add_next_index_string(return_value, PQgetvalue(pgsql_result, pg_row, colno), 1); } } } @@ -3151,12 +3151,12 @@ PHP_FUNCTION(pg_untrace) zval *pgsql_link = NULL; int id = -1, argc = ZEND_NUM_ARGS(); PGconn *pgsql; - + if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) { return; } - if (argc == 0) { + if (argc == 0) { id = PGG(default_link); CHECK_DEFAULT_LINK(id); } @@ -3188,7 +3188,7 @@ PHP_FUNCTION(pg_lo_create) oid = pgsql_link; pgsql_link = NULL; } - + if (pgsql_link == NULL) { id = PGG(default_link); CHECK_DEFAULT_LINK(id); @@ -3198,7 +3198,7 @@ PHP_FUNCTION(pg_lo_create) } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); - + if (oid) { #ifndef HAVE_PG_LO_CREATE php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Passing OID value is not supported. Upgrade your PostgreSQL"); @@ -3377,7 +3377,7 @@ PHP_FUNCTION(pg_lo_open) } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); - + /* r/w/+ is little bit more PHP-like than INV_READ/INV_WRITE and a lot of faster to type. Unfortunately, doesn't behave the same way as fopen()... (Jouni) @@ -3447,7 +3447,7 @@ PHP_FUNCTION(pg_lo_close) } ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_lofp, -1, "PostgreSQL large object", le_lofp); - + if (lo_close((PGconn *)pgsql->conn, pgsql->lofd) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to close PostgreSQL large object descriptor %d", pgsql->lofd); RETVAL_FALSE; @@ -3481,7 +3481,7 @@ PHP_FUNCTION(pg_lo_read) if (argc > 1) { buf_len = len; } - + buf = (char *) safe_emalloc(sizeof(char), (buf_len+1), 0); if ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))<0) { efree(buf); @@ -3543,7 +3543,7 @@ PHP_FUNCTION(pg_lo_read_all) volatile int nbytes; char buf[PGSQL_LO_READ_BUF_SIZE]; pgLofp *pgsql; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_id) == FAILURE) { return; } @@ -3587,7 +3587,7 @@ PHP_FUNCTION(pg_lo_import) else { WRONG_PARAM_COUNT; } - + if (php_check_open_basedir(file_in TSRMLS_CC)) { RETURN_FALSE; } @@ -3720,7 +3720,7 @@ PHP_FUNCTION(pg_lo_export) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 2 or 3 arguments"); RETURN_FALSE; } - + if (php_check_open_basedir(file_out TSRMLS_CC)) { RETURN_FALSE; } @@ -3861,7 +3861,7 @@ PHP_FUNCTION(pg_set_error_verbosity) if (pgsql_link == NULL && id == -1) { RETURN_FALSE; - } + } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); @@ -3920,7 +3920,7 @@ PHP_FUNCTION(pg_client_encoding) if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) { return; } - + if (argc == 0) { id = PGG(default_link); CHECK_DEFAULT_LINK(id); @@ -3928,7 +3928,7 @@ PHP_FUNCTION(pg_client_encoding) if (pgsql_link == NULL && id == -1) { RETURN_FALSE; - } + } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); @@ -3958,7 +3958,7 @@ PHP_FUNCTION(pg_end_copy) if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) { return; } - + if (argc == 0) { id = PGG(default_link); CHECK_DEFAULT_LINK(id); @@ -4005,7 +4005,7 @@ PHP_FUNCTION(pg_put_line) if (pgsql_link == NULL && id == -1) { RETURN_FALSE; - } + } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); @@ -4117,7 +4117,7 @@ PHP_FUNCTION(pg_copy_to) csv = (char *)erealloc(csv, strlen(csv) + sizeof(char)*(COPYBUFSIZ+1)); strcat(csv, copybuf); } - + switch (ret) { case EOF: @@ -4326,7 +4326,7 @@ PHP_FUNCTION(pg_escape_string) break; } - to = (char *) safe_emalloc(from_len, 2, 1); + to = (char *) safe_emalloc_string(from_len, 2, 1); #ifdef HAVE_PQESCAPE_CONN if (pgsql_link != NULL || id != -1) { ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); @@ -4375,7 +4375,7 @@ PHP_FUNCTION(pg_escape_bytea) #endif to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len); - RETVAL_STRINGL(to, to_len-1, 1); /* to_len includes additional '\0' */ + RETVAL_STRINGL_CHECK(to, to_len-1, 1); /* to_len includes additional '\0' */ PQfreemem(to); } /* }}} */ @@ -4461,7 +4461,7 @@ static unsigned char * php_pgsql_unescape_bytea(unsigned char *strtext, size_t * if (isdigit(*sp)) /* state=4 */ { unsigned char *start, *end, buf[4]; /* 000 + '\0' */ - + bp -= 3; memcpy(buf, sp-2, 3); buf[3] = '\0'; @@ -4562,7 +4562,7 @@ static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_l to = estrdup(tmp); PGSQLfree(tmp); - RETURN_STRING(to, 0); + RETVAL_STRINGL_CHECK(to, strlen(to), 0); } /* {{{ proto string pg_escape_literal([resource connection,] string data) @@ -4596,7 +4596,7 @@ PHP_FUNCTION(pg_result_error) &result) == FAILURE) { RETURN_FALSE; } - + ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; @@ -4624,7 +4624,7 @@ PHP_FUNCTION(pg_result_error_field) &result, &fieldcode) == FAILURE) { RETURN_FALSE; } - + ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result); pgsql_result = pg_result->result; @@ -4706,14 +4706,14 @@ PHP_FUNCTION(pg_connection_reset) zval *pgsql_link; int id = -1; PGconn *pgsql; - + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) { RETURN_FALSE; } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); - + PQreset(pgsql); if (PQstatus(pgsql) == CONNECTION_BAD) { RETURN_FALSE; @@ -4729,11 +4729,11 @@ PHP_FUNCTION(pg_connection_reset) /* {{{ php_pgsql_flush_query */ -static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC) +static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC) { PGresult *res; int leftover = 0; - + if (PQ_SETNONBLOCKING(pgsql, 1)) { php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to nonblocking mode"); return -1; @@ -4750,7 +4750,7 @@ static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC) /* {{{ php_pgsql_do_async */ -static void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type) +static void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type) { zval *pgsql_link; int id = -1; @@ -4928,7 +4928,7 @@ PHP_FUNCTION(pg_send_query_params) if (num_params > 0) { int i = 0; params = (char **)safe_emalloc(sizeof(char *), num_params, 0); - + for(i = 0; i < num_params; i++) { if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter"); @@ -5200,7 +5200,7 @@ PHP_FUNCTION(pg_get_result) } ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); - + pgsql_result = PQgetResult(pgsql); if (!pgsql_result) { /* no result */ @@ -5279,11 +5279,11 @@ PHP_FUNCTION(pg_get_notify) if (result_type & PGSQL_NUM) { add_index_string(return_value, 0, pgsql_notify->relname, 1); add_index_long(return_value, 1, pgsql_notify->be_pid); -#if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS +#if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) { -#else +#else if (atof(PG_VERSION) >= 9.0) { -#endif +#endif #if HAVE_PQPARAMETERSTATUS add_index_string(return_value, 2, pgsql_notify->extra, 1); #endif @@ -5292,11 +5292,11 @@ PHP_FUNCTION(pg_get_notify) if (result_type & PGSQL_ASSOC) { add_assoc_string(return_value, "message", pgsql_notify->relname, 1); add_assoc_long(return_value, "pid", pgsql_notify->be_pid); -#if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS +#if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) { -#else +#else if (atof(PG_VERSION) >= 9.0) { -#endif +#endif #if HAVE_PQPARAMETERSTATUS add_assoc_string(return_value, "payload", pgsql_notify->extra, 1); #endif @@ -5569,7 +5569,7 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z add_assoc_zval(meta, name, elem); } PQclear(pg_result); - + return SUCCESS; } @@ -5743,7 +5743,7 @@ static int php_pgsql_convert_match(const char *str, size_t str_len, const char * /* {{{ php_pgsql_add_quote * add quotes around string. */ -static int php_pgsql_add_quotes(zval *src, zend_bool should_free TSRMLS_DC) +static int php_pgsql_add_quotes(zval *src, zend_bool should_free TSRMLS_DC) { smart_str str = {0}; @@ -5784,7 +5784,7 @@ static int php_pgsql_add_quotes(zval *src, zend_bool should_free TSRMLS_DC) /* {{{ php_pgsql_convert * check and convert array values (fieldname=>vlaue pair) for sql */ -PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, const zval *values, zval *result, ulong opt TSRMLS_DC) +PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, const zval *values, zval *result, ulong opt TSRMLS_DC) { HashPosition pos; char *field = NULL; @@ -5943,11 +5943,11 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con ZVAL_DOUBLE(new_val, Z_DVAL_PP(val)); convert_to_long_ex(&new_val); break; - + case IS_LONG: ZVAL_LONG(new_val, Z_LVAL_PP(val)); break; - + case IS_NULL: ZVAL_STRINGL(new_val, "NULL", sizeof("NULL")-1, 1); break; @@ -6130,7 +6130,7 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con } } break; - + case IS_NULL: ZVAL_STRINGL(new_val, "NULL", sizeof("NULL")-1, 1); break; @@ -6251,14 +6251,14 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con interval values can be written with the following syntax: [@] quantity unit [quantity unit...] [direction] - + Where: quantity is a number (possibly signed); unit is second, minute, hour, day, week, month, year, decade, century, millennium, or abbreviations or plurals of these units [note not *all* abbreviations] ; direction can be ago or empty. The at sign (@) is optional noise. - + ... - + Quantities of days, hours, minutes, and seconds can be specified without explicit unit markings. For example, '1 12:59:10' is read the same as '1 day 12 hours 59 min 10 sec'. @@ -6274,7 +6274,7 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con "decades|decade|dec|decs|" "years|year|y|" "months|month|mon|" - "weeks|week|w|" + "weeks|week|w|" "days|day|d|" "hours|hour|hr|hrs|h|" "minutes|minute|mins|min|m|" @@ -6289,7 +6289,7 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con "years|year|y|" "months|month|mon|" "weeks|week|w|" - "days|day|d))+" + "days|day|d))+" "([-+]?[ \\t]+" "([0-9]+[ \\t]+)+" /* dd */ "(([0-9]{1,2}:){0,2}[0-9]{0,2})" /* hh:[mm:[ss]] */ @@ -6369,7 +6369,7 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field); } break; - + #endif case PG_MACADDR: switch(Z_TYPE_PP(val)) { @@ -6593,12 +6593,12 @@ PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var } querystr.len--; smart_str_appends(&querystr, ") VALUES ("); - + /* make values string */ for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos); zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&val, &pos) == SUCCESS; zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos)) { - + /* we can avoid the key_type check here, because we tested it in the other loop */ switch(Z_TYPE_PP(val)) { case IS_STRING: @@ -6646,7 +6646,7 @@ no_values: else if (opt & PGSQL_DML_STRING) { ret = SUCCESS; } - + cleanup: if (!(opt & PGSQL_DML_NO_CONV) && converted) { zval_dtor(converted); @@ -6684,7 +6684,7 @@ PHP_FUNCTION(pg_insert) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified"); RETURN_FALSE; } - + ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); if (php_pgsql_flush_query(pg_link TSRMLS_CC)) { @@ -6812,7 +6812,7 @@ static inline int build_assignment_string(PGconn *pg_link, smart_str *querystr, /* {{{ php_pgsql_update */ -PHP_PGSQL_API int php_pgsql_update(PGconn *pg_link, const char *table, zval *var_array, zval *ids_array, ulong opt, char **sql TSRMLS_DC) +PHP_PGSQL_API int php_pgsql_update(PGconn *pg_link, const char *table, zval *var_array, zval *ids_array, ulong opt, char **sql TSRMLS_DC) { zval *var_converted = NULL, *ids_converted = NULL; smart_str querystr = {0}; @@ -6850,9 +6850,9 @@ PHP_PGSQL_API int php_pgsql_update(PGconn *pg_link, const char *table, zval *var if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(var_array), 0, ",", 1, opt TSRMLS_CC)) goto cleanup; - + smart_str_appends(&querystr, " WHERE "); - + if (build_assignment_string(pg_link, &querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1, opt TSRMLS_CC)) goto cleanup; @@ -6903,7 +6903,7 @@ PHP_FUNCTION(pg_update) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified"); RETURN_FALSE; } - + ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); if (php_pgsql_flush_query(pg_link TSRMLS_CC)) { @@ -6921,7 +6921,7 @@ PHP_FUNCTION(pg_update) /* {{{ php_pgsql_delete */ -PHP_PGSQL_API int php_pgsql_delete(PGconn *pg_link, const char *table, zval *ids_array, ulong opt, char **sql TSRMLS_DC) +PHP_PGSQL_API int php_pgsql_delete(PGconn *pg_link, const char *table, zval *ids_array, ulong opt, char **sql TSRMLS_DC) { zval *ids_converted = NULL; smart_str querystr = {0}; @@ -6995,7 +6995,7 @@ PHP_FUNCTION(pg_delete) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified"); RETURN_FALSE; } - + ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); if (php_pgsql_flush_query(pg_link TSRMLS_CC)) { @@ -7008,12 +7008,12 @@ PHP_FUNCTION(pg_delete) RETURN_STRING(sql, 0); } RETURN_TRUE; -} +} /* }}} */ /* {{{ php_pgsql_result2array */ -PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array TSRMLS_DC) +PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array TSRMLS_DC) { zval *row; char *field_name; @@ -7042,7 +7042,7 @@ PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array TS data = safe_estrndup(element, element_len); data_len = element_len; - + field_name = PQfname(pg_result, i); add_assoc_stringl(row, field_name, data, data_len, 0); } @@ -7133,7 +7133,7 @@ PHP_FUNCTION(pg_select) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified"); RETURN_FALSE; } - + ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink); if (php_pgsql_flush_query(pg_link TSRMLS_CC)) { diff --git a/ext/standard/string.c b/ext/standard/string.c index 9498496fce..da473d985c 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2401,7 +2401,7 @@ PHP_FUNCTION(substr_replace) l = Z_STRLEN_PP(str); } - if ((f + l) > Z_STRLEN_PP(str)) { + if (f > Z_STRLEN_PP(str) - l) { l = Z_STRLEN_PP(str) - f; } if (Z_TYPE_PP(repl) == IS_ARRAY) { @@ -2414,7 +2414,7 @@ PHP_FUNCTION(substr_replace) repl_len = Z_STRLEN_PP(repl); } result_len = Z_STRLEN_PP(str) - l + repl_len; - result = emalloc(result_len + 1); + result = safe_emalloc_string(1, result_len, 1); memcpy(result, Z_STRVAL_PP(str), f); if (repl_len) { @@ -2556,7 +2556,7 @@ PHP_FUNCTION(substr_replace) result_len += Z_STRLEN_P(repl_str); zend_hash_move_forward_ex(Z_ARRVAL_PP(repl), &pos_repl); - result = emalloc(result_len + 1); + result = safe_emalloc_string(1, result_len, 1); memcpy(result, Z_STRVAL_P(orig_str), f); memcpy((result + f), Z_STRVAL_P(repl_str), Z_STRLEN_P(repl_str)); @@ -2565,7 +2565,7 @@ PHP_FUNCTION(substr_replace) zval_dtor(repl_str); } } else { - result = emalloc(result_len + 1); + result = safe_emalloc_string(1, result_len, 1); memcpy(result, Z_STRVAL_P(orig_str), f); memcpy((result + f), Z_STRVAL_P(orig_str) + f + l, Z_STRLEN_P(orig_str) - f - l); @@ -2573,7 +2573,7 @@ PHP_FUNCTION(substr_replace) } else { result_len += Z_STRLEN_PP(repl); - result = emalloc(result_len + 1); + result = safe_emalloc_string(1, result_len, 1); memcpy(result, Z_STRVAL_P(orig_str), f); memcpy((result + f), Z_STRVAL_PP(repl), Z_STRLEN_PP(repl)); @@ -2620,7 +2620,7 @@ PHP_FUNCTION(quotemeta) RETURN_FALSE; } - str = safe_emalloc(2, old_len, 1); + str = safe_emalloc_string(2, old_len, 1); for (p = old, q = str; p != old_end; p++) { c = *p; @@ -3646,7 +3646,7 @@ PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_l if (Z_STRLEN_P(result) < 0) { zend_error(E_ERROR, "String size overflow"); } - Z_STRVAL_P(result) = target = safe_emalloc(char_count, to_len, len + 1); + Z_STRVAL_P(result) = target = safe_emalloc_string(char_count, to_len, len + 1); Z_TYPE_P(result) = IS_STRING; if (case_sensitivity) { @@ -3776,7 +3776,7 @@ PHPAPI char *php_str_to_str_ex(char *haystack, int length, } return new_str; } else { - new_str = safe_emalloc(count, str_len - needle_len, length + 1); + new_str = safe_emalloc_string(count, str_len - needle_len, length + 1); } } @@ -4307,10 +4307,7 @@ PHP_FUNCTION(nl2br) size_t repl_len = is_xhtml ? (sizeof("
") - 1) : (sizeof("
") - 1); new_length = str_len + repl_cnt * repl_len; - if (UNEXPECTED(new_length > INT_MAX)) { - zend_error(E_ERROR, "String size overflow"); - } - tmp = target = safe_emalloc(repl_cnt, repl_len, str_len + 1); + tmp = target = safe_emalloc_string(repl_cnt, repl_len, str_len + 1); } while (str < end) { @@ -5303,7 +5300,7 @@ PHP_FUNCTION(str_pad) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding length is too long"); return; } - result = (char *)emalloc(input_len + num_pad_chars + 1); + result = (char *)safe_emalloc_string(1, input_len, num_pad_chars + 1); /* We need to figure out the left/right padding lengths. */ switch (pad_type_val) { diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 5912f9143d..96a76efbdf 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -12,7 +12,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Stig Sæther Bakken | + | Authors: Stig Sæther Bakken | | Thies C. Arntzen | | Sterling Hughes | +----------------------------------------------------------------------+ @@ -638,7 +638,7 @@ PHPAPI char *xml_utf8_encode(const char *s, int len, int *newlen, const XML_Char } /* This is the theoretical max (will never get beyond len * 2 as long * as we are converting from single-byte characters, though) */ - newbuf = safe_emalloc(len, 4, 1); + newbuf = safe_emalloc_string(len, 4, 1); while (pos > 0) { c = encoder ? encoder((unsigned char)(*s)) : (unsigned short)(*s); if (c < 0x80) { diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index ea0d502e90..e33b2ccd21 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -82,7 +82,7 @@ static int php_zlib_output_encoding(TSRMLS_D) zval **enc; if (!ZLIBG(compression_coding)) { - if ((PG(http_globals)[TRACK_VARS_SERVER] || zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC)) && + if ((PG(http_globals)[TRACK_VARS_SERVER] || zend_is_auto_global(ZEND_STRL("_SERVER") TSRMLS_CC)) && SUCCESS == zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void *) &enc)) { convert_to_string(*enc); if (strstr(Z_STRVAL_PP(enc), "gzip")) { @@ -574,7 +574,7 @@ static PHP_FUNCTION(gzfile) /* Now loop through the file and do the magic quotes thing if needed */ memset(buf, 0, sizeof(buf)); - + while (php_stream_gets(stream, buf, sizeof(buf) - 1) != NULL) { add_index_string(return_value, i++, buf, 1); } @@ -693,7 +693,7 @@ static PHP_FUNCTION(name) \ if (SUCCESS != php_zlib_decode(in_buf, in_len, &out_buf, &out_len, encoding, max_len TSRMLS_CC)) { \ RETURN_FALSE; \ } \ - RETURN_STRINGL(out_buf, out_len, 0); \ + RETVAL_STRINGL_CHECK(out_buf, out_len, 0); \ } /* {{{ proto binary zlib_encode(binary data, int encoding[, int level = -1]) @@ -931,7 +931,7 @@ static PHP_INI_MH(OnUpdate_zlib_output_handler) return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); } /* }}} */ - + /* {{{ INI */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zlib.output_compression", "0", PHP_INI_ALL, OnUpdate_zlib_output_compression, output_compression_default, zend_zlib_globals, zlib_globals) -- cgit v1.2.1 From 223266e4e46b9188353db93771369078c2e94353 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 4 Sep 2016 22:07:35 -0700 Subject: Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile --- ext/phar/tests/bug72928.phpt | 18 ++++++++++++++++++ ext/phar/tests/bug72928.zip | Bin 0 -> 140 bytes ext/phar/util.c | 28 ++++++++++++++++++++++++++++ ext/phar/zip.c | 2 +- 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 ext/phar/tests/bug72928.phpt create mode 100644 ext/phar/tests/bug72928.zip diff --git a/ext/phar/tests/bug72928.phpt b/ext/phar/tests/bug72928.phpt new file mode 100644 index 0000000000..8e6a95418c --- /dev/null +++ b/ext/phar/tests/bug72928.phpt @@ -0,0 +1,18 @@ +--TEST-- +Phar: #72928 (Out of bound when verify signature of zip phar in phar_parse_zipfile) +--SKIPIF-- + +--FILE-- +getMessage()."\n"; +} +?> +DONE +--EXPECTF-- +phar error: signature cannot be read in zip-based phar "%sbug72928.zip" +DONE \ No newline at end of file diff --git a/ext/phar/tests/bug72928.zip b/ext/phar/tests/bug72928.zip new file mode 100644 index 0000000000..c480c5f537 Binary files /dev/null and b/ext/phar/tests/bug72928.zip differ diff --git a/ext/phar/util.c b/ext/phar/util.c index 4bbd8676cb..828be8f9a2 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1650,6 +1650,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[64]; PHP_SHA512_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_SHA512Init(&context); read_len = end_of_phar; @@ -1683,6 +1690,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[32]; PHP_SHA256_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_SHA256Init(&context); read_len = end_of_phar; @@ -1724,6 +1738,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[20]; PHP_SHA1_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_SHA1Init(&context); read_len = end_of_phar; @@ -1757,6 +1778,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[16]; PHP_MD5_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_MD5Init(&context); read_len = end_of_phar; diff --git a/ext/phar/zip.c b/ext/phar/zip.c index bf895e7dfe..ed156a2d00 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -430,7 +430,7 @@ foundit: php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET); sig = (char *) emalloc(entry.uncompressed_filesize); read = php_stream_read(fp, sig, entry.uncompressed_filesize); - if (read != entry.uncompressed_filesize) { + if (read != entry.uncompressed_filesize || read <= 8) { php_stream_close(sigfile); efree(sig); PHAR_ZIP_FAIL("signature cannot be read"); -- cgit v1.2.1 From ba5ac0d360f0f2cab3ab5a478c601e4071acd0f2 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 4 Sep 2016 22:18:19 -0700 Subject: Add more checks for int overflow --- ext/recode/recode.c | 24 ++++++++++++------------ ext/standard/file.c | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ext/recode/recode.c b/ext/recode/recode.c index 7d141e7928..cde03aacd1 100644 --- a/ext/recode/recode.c +++ b/ext/recode/recode.c @@ -15,7 +15,7 @@ | Author: Kristian Koehntopp | +----------------------------------------------------------------------+ */ - + /* $Id$ */ /* {{{ includes & prototypes */ @@ -62,7 +62,7 @@ ZEND_END_MODULE_GLOBALS(recode) #else # define ReSG(v) (recode_globals.v) #endif - + ZEND_DECLARE_MODULE_GLOBALS(recode) static PHP_GINIT_FUNCTION(recode); @@ -89,13 +89,13 @@ static const zend_function_entry php_recode_functions[] = { zend_module_entry recode_module_entry = { STANDARD_MODULE_HEADER, - "recode", - php_recode_functions, - PHP_MINIT(recode), - PHP_MSHUTDOWN(recode), + "recode", + php_recode_functions, + PHP_MINIT(recode), + PHP_MSHUTDOWN(recode), + NULL, NULL, - NULL, - PHP_MINFO(recode), + PHP_MINFO(recode), NO_VERSION_YET, PHP_MODULE_GLOBALS(recode), PHP_GINIT(recode), @@ -164,14 +164,14 @@ PHP_FUNCTION(recode_string) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal recode request '%s'", req); goto error_exit; } - + recode_buffer_to_buffer(request, str, str_len, &r, &r_len, &r_alen); if (!r) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Recoding failed."); error_exit: RETVAL_FALSE; } else { - RETVAL_STRINGL(r, r_len, 1); + RETVAL_STRINGL_CHECK(r, r_len, 1); free(r); } @@ -202,7 +202,7 @@ PHP_FUNCTION(recode_file) if (FAILURE == php_stream_cast(instream, PHP_STREAM_AS_STDIO, (void**)&in_fp, REPORT_ERRORS)) { RETURN_FALSE; } - + if (FAILURE == php_stream_cast(outstream, PHP_STREAM_AS_STDIO, (void**)&out_fp, REPORT_ERRORS)) { RETURN_FALSE; } @@ -217,7 +217,7 @@ PHP_FUNCTION(recode_file) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal recode request '%s'", req); goto error_exit; } - + if (!recode_file_to_file(request, in_fp, out_fp)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Recoding failed."); goto error_exit; diff --git a/ext/standard/file.c b/ext/standard/file.c index f3b6df1274..440276ab6e 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -1040,7 +1040,7 @@ PHPAPI PHP_FUNCTION(fgets) } } - ZVAL_STRINGL(return_value, buf, line_len, 0); + RETVAL_STRINGL_CHECK(buf, line_len, 0); /* resize buffer if it's much larger than the result. * Only needed if the user requested a buffer size. */ if (argc > 1 && Z_STRLEN_P(return_value) < len / 2) { @@ -1124,7 +1124,7 @@ PHPAPI PHP_FUNCTION(fgetss) retval_len = php_strip_tags(retval, actual_len, &stream->fgetss_state, allowed_tags, allowed_tags_len); - RETURN_STRINGL(retval, retval_len, 0); + RETVAL_STRINGL_CHECK(retval, retval_len, 0); } /* }}} */ -- cgit v1.2.1 From 6d55ba265637d6adf0ba7e9c9ef11187d1ec2f5b Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 5 Sep 2016 18:01:35 -0700 Subject: Fix bug #73007: add locale length check --- ext/intl/msgformat/msgformat_format.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/intl/msgformat/msgformat_format.c b/ext/intl/msgformat/msgformat_format.c index 25c9619133..9b6df38ee3 100644 --- a/ext/intl/msgformat/msgformat_format.c +++ b/ext/intl/msgformat/msgformat_format.c @@ -117,6 +117,8 @@ PHP_FUNCTION( msgfmt_format_message ) RETURN_FALSE; } + INTL_CHECK_LOCALE_LEN(slocale_len); + msgformat_data_init(&mfo->mf_data TSRMLS_CC); if(pattern && pattern_len) { -- cgit v1.2.1 From 65c8caafa83ca78a8b2fa22257b4dea85b6114e5 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 5 Sep 2016 18:10:51 -0700 Subject: Also fix overflow in wordwrap --- ext/standard/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index da473d985c..9acbe03792 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1011,7 +1011,7 @@ PHP_FUNCTION(wordwrap) /* free unused memory */ newtext = erealloc(newtext, newtextlen+1); - RETURN_STRINGL(newtext, newtextlen, 0); + RETVAL_STRINGL_CHECK(newtext, newtextlen, 0); } } /* }}} */ -- cgit v1.2.1 From b88393f08a558eec14964a55d3c680fe67407712 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 5 Sep 2016 23:42:31 -0700 Subject: Fix bug #72860: wddx_deserialize use-after-free --- ext/wddx/tests/bug72860.phpt | 27 +++++++++++++++++++++++++++ ext/wddx/wddx.c | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 ext/wddx/tests/bug72860.phpt diff --git a/ext/wddx/tests/bug72860.phpt b/ext/wddx/tests/bug72860.phpt new file mode 100644 index 0000000000..6385457e8e --- /dev/null +++ b/ext/wddx/tests/bug72860.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #72860: wddx_deserialize use-after-free +--SKIPIF-- + +--FILE-- + + + + + + + +XML; + +var_dump(wddx_deserialize($xml)); +?> +DONE +--EXPECT-- +NULL +DONE \ No newline at end of file diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index d7bd295832..b02d2f07de 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -230,7 +230,8 @@ static int wddx_stack_destroy(wddx_stack *stack) if (stack->elements) { for (i = 0; i < stack->top; i++) { - if (((st_entry *)stack->elements[i])->data) { + if (((st_entry *)stack->elements[i])->data + && ((st_entry *)stack->elements[i])->type != ST_FIELD) { zval_ptr_dtor(&((st_entry *)stack->elements[i])->data); } if (((st_entry *)stack->elements[i])->varname) { -- cgit v1.2.1 From ecb7f58a069be0dec4a6131b6351a761f808f22e Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 11 Sep 2016 20:24:13 -0700 Subject: Fix bug #73029 - Missing type check when unserializing SplArray --- ext/spl/spl_array.c | 10 ++++++---- ext/spl/tests/bug73029.phpt | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 ext/spl/tests/bug73029.phpt diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 42a8e7aa44..700d6093dd 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -308,7 +308,7 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, long index; HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if (!offset) { + if (!offset || !ht) { return &EG(uninitialized_zval_ptr); } @@ -626,7 +626,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); switch(Z_TYPE_P(offset)) { - case IS_STRING: + case IS_STRING: if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &tmp) != FAILURE) { if (check_empty == 2) { return 1; @@ -638,7 +638,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o case IS_DOUBLE: case IS_RESOURCE: - case IS_BOOL: + case IS_BOOL: case IS_LONG: if (offset->type == IS_DOUBLE) { index = (long)Z_DVAL_P(offset); @@ -1810,7 +1810,9 @@ SPL_METHOD(Array, unserialize) intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK; zval_ptr_dtor(&intern->array); ALLOC_INIT_ZVAL(intern->array); - if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) { + if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC) + || (Z_TYPE_P(intern->array) != IS_ARRAY && Z_TYPE_P(intern->array) != IS_OBJECT)) { + zval_ptr_dtor(&intern->array); goto outexcept; } var_push_dtor(&var_hash, &intern->array); diff --git a/ext/spl/tests/bug73029.phpt b/ext/spl/tests/bug73029.phpt new file mode 100644 index 0000000000..a379f8005e --- /dev/null +++ b/ext/spl/tests/bug73029.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #73029: Missing type check when unserializing SplArray +--FILE-- +getMessage() . "\n"; +} +?> +DONE +--EXPECTF-- +Error at offset 10 of 19 bytes +DONE -- cgit v1.2.1 From 7381d4c00e32d86573b55540d379ef0c6da3c09d Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 11 Sep 2016 20:58:55 -0700 Subject: Add check in fgetcsv in case sizeof(unit) != sizeof(size_t) --- ext/standard/file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/standard/file.c b/ext/standard/file.c index 440276ab6e..067f9614eb 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -2301,6 +2301,10 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, char /* 3. Now pass our field back to php */ *comp_end = '\0'; + if (UNEXPECTED((comp_end - temp) > INT_MAX)) { + zend_error_noreturn(E_WARNING, "String overflow, max size is %d", INT_MAX); + break; + } add_next_index_stringl(return_value, temp, comp_end - temp, 1); } while (inc_len > 0); -- cgit v1.2.1 From 6a7cc8ff85827fa9ac715b3a83c2d9147f33cd43 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 11 Sep 2016 21:19:29 -0700 Subject: Fix bug #73052 - Memory Corruption in During Deserialized-object Destruction --- Zend/zend_objects_API.c | 6 +-- ext/standard/tests/serialize/bug73052.phpt | 18 +++++++++ ext/standard/var_unserializer.c | 61 +++++++++++++++--------------- ext/standard/var_unserializer.re | 1 + 4 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 ext/standard/tests/serialize/bug73052.phpt diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 56c47b7f84..cdc0b69fbf 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -215,7 +215,7 @@ ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, } zend_end_try(); } } - + /* re-read the object from the object store as the store might have been reallocated in the dtor */ obj = &EG(objects_store).object_buckets[handle].bucket.obj; @@ -306,8 +306,8 @@ ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC) { zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle]; - - obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);; + + obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject); obj_bucket->destructor_called = 1; } diff --git a/ext/standard/tests/serialize/bug73052.phpt b/ext/standard/tests/serialize/bug73052.phpt new file mode 100644 index 0000000000..63b484bf14 --- /dev/null +++ b/ext/standard/tests/serialize/bug73052.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #73052: Memory Corruption in During Deserialized-object Destruction +--FILE-- +ryat = null; + } +} + +$poc = 'O:3:"obj":1:{'; +var_dump(unserialize($poc)); +?> +--EXPECTF-- +Notice: unserialize(): Error at offset 13 of 13 bytes in %sbug73052.php on line %d +bool(false) diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index c8e6f8a0ca..549149267e 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -437,6 +437,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) /* We've got partially constructed object on our hands here. Wipe it. */ if(Z_TYPE_PP(rval) == IS_OBJECT) { zend_hash_clean(Z_OBJPROP_PP(rval)); + zend_object_store_ctor_failed(*rval TSRMLS_CC); } ZVAL_NULL(*rval); return 0; @@ -491,7 +492,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 495 "ext/standard/var_unserializer.c" +#line 496 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -551,9 +552,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 860 "ext/standard/var_unserializer.re" +#line 861 "ext/standard/var_unserializer.re" { return 0; } -#line 557 "ext/standard/var_unserializer.c" +#line 558 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -596,13 +597,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 854 "ext/standard/var_unserializer.re" +#line 855 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 606 "ext/standard/var_unserializer.c" +#line 607 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -633,7 +634,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 707 "ext/standard/var_unserializer.re" +#line 708 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -780,7 +781,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 784 "ext/standard/var_unserializer.c" +#line 785 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -805,7 +806,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 698 "ext/standard/var_unserializer.re" +#line 699 "ext/standard/var_unserializer.re" { if (!var_hash) return 0; @@ -814,7 +815,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 818 "ext/standard/var_unserializer.c" +#line 819 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -835,7 +836,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 677 "ext/standard/var_unserializer.re" +#line 678 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -856,7 +857,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 860 "ext/standard/var_unserializer.c" +#line 861 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -877,7 +878,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 642 "ext/standard/var_unserializer.re" +#line 643 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -912,7 +913,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 916 "ext/standard/var_unserializer.c" +#line 917 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -933,7 +934,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 609 "ext/standard/var_unserializer.re" +#line 610 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -966,7 +967,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 970 "ext/standard/var_unserializer.c" +#line 971 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1054,7 +1055,7 @@ yy61: } yy63: ++YYCURSOR; -#line 599 "ext/standard/var_unserializer.re" +#line 600 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1064,7 +1065,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1068 "ext/standard/var_unserializer.c" +#line 1069 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1123,7 +1124,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 584 "ext/standard/var_unserializer.re" +#line 585 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1138,7 +1139,7 @@ yy73: return 1; } -#line 1142 "ext/standard/var_unserializer.c" +#line 1143 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1165,7 +1166,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 557 "ext/standard/var_unserializer.re" +#line 558 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1192,7 +1193,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1196 "ext/standard/var_unserializer.c" +#line 1197 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1200,24 +1201,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 550 "ext/standard/var_unserializer.re" +#line 551 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1211 "ext/standard/var_unserializer.c" +#line 1212 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 543 "ext/standard/var_unserializer.re" +#line 544 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1221 "ext/standard/var_unserializer.c" +#line 1222 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1240,7 +1241,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 520 "ext/standard/var_unserializer.re" +#line 521 "ext/standard/var_unserializer.re" { long id; @@ -1263,7 +1264,7 @@ yy91: return 1; } -#line 1267 "ext/standard/var_unserializer.c" +#line 1268 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1286,7 +1287,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 499 "ext/standard/var_unserializer.re" +#line 500 "ext/standard/var_unserializer.re" { long id; @@ -1307,9 +1308,9 @@ yy97: return 1; } -#line 1311 "ext/standard/var_unserializer.c" +#line 1312 "ext/standard/var_unserializer.c" } -#line 862 "ext/standard/var_unserializer.re" +#line 863 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 11b93c522b..ce84bf5eb4 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -441,6 +441,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) /* We've got partially constructed object on our hands here. Wipe it. */ if(Z_TYPE_PP(rval) == IS_OBJECT) { zend_hash_clean(Z_OBJPROP_PP(rval)); + zend_object_store_ctor_failed(*rval TSRMLS_CC); } ZVAL_NULL(*rval); return 0; -- cgit v1.2.1 From f5a9592ad8d2b60cabbaff00662477528ecefb48 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 11 Sep 2016 21:37:44 -0700 Subject: Fix bug #73035 (Out of bound when verify signature of tar phar in phar_parse_tarfile) --- ext/phar/tar.c | 2 +- ext/phar/tests/bug73035.phpt | 18 ++++++++++++++++++ ext/phar/tests/bug73035.tar | Bin 0 -> 10240 bytes 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 ext/phar/tests/bug73035.phpt create mode 100644 ext/phar/tests/bug73035.tar diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 62edcb59f1..898ff859ab 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -286,7 +286,7 @@ bail: } curloc = php_stream_tell(fp); read = php_stream_read(fp, buf, size); - if (read != size) { + if (read != size || read <= 8) { if (error) { spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be read", fname); } diff --git a/ext/phar/tests/bug73035.phpt b/ext/phar/tests/bug73035.phpt new file mode 100644 index 0000000000..5928428abc --- /dev/null +++ b/ext/phar/tests/bug73035.phpt @@ -0,0 +1,18 @@ +--TEST-- +Phar: #73035 (Out of bound when verify signature of tar phar in phar_parse_tarfile) +--SKIPIF-- + +--FILE-- +getMessage()."\n"; +} +?> +DONE +--EXPECTF-- +phar error: tar-based phar "%sbug73035.tar" signature cannot be read +DONE \ No newline at end of file diff --git a/ext/phar/tests/bug73035.tar b/ext/phar/tests/bug73035.tar new file mode 100644 index 0000000000..d8e426866b Binary files /dev/null and b/ext/phar/tests/bug73035.tar differ -- cgit v1.2.1 From c4cca4c20e75359c9a13a1f9a36cb7b4e9601d29 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 12 Sep 2016 00:35:01 -0700 Subject: Fix bug #73065: Out-Of-Bounds Read in php_wddx_push_element of wddx.c --- ext/wddx/tests/bug73065.phpt | 98 ++++++++++++++++++++++++++++++++++++++++++++ ext/wddx/wddx.c | 19 +++++---- 2 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 ext/wddx/tests/bug73065.phpt diff --git a/ext/wddx/tests/bug73065.phpt b/ext/wddx/tests/bug73065.phpt new file mode 100644 index 0000000000..aa301aa838 --- /dev/null +++ b/ext/wddx/tests/bug73065.phpt @@ -0,0 +1,98 @@ +--TEST-- +Bug #73065: Out-Of-Bounds Read in php_wddx_push_element of wddx.c +--SKIPIF-- + +--FILE-- + + + + + + + + + + + + + + +XML; + +$xml2 = << + + + + + + + + +XML; + +$xml3 = << + + + + + + + + +XML; + +$xml4 = << + + + + + + + + +XML; + +$xml5 = << + + + + + + + + +XML; + +for($i=1;$i<=5;$i++) { + $xmlvar = "xml$i"; + $array = wddx_deserialize($$xmlvar); + var_dump($array); +} +?> +DONE +--EXPECTF-- +array(0) { +} +array(0) { +} +array(0) { +} +array(1) { + [0]=> + array(0) { + } +} +array(0) { +} +DONE \ No newline at end of file diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index b02d2f07de..0e77826ce8 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -780,10 +780,10 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X int i; if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp(atts[i], EL_CHAR_CODE) && atts[++i] && atts[i][0]) { + if (!strcmp(atts[i], EL_CHAR_CODE) && atts[i+1] && atts[i+1][0]) { char tmp_buf[2]; - snprintf(tmp_buf, sizeof(tmp_buf), "%c", (char)strtol(atts[i], NULL, 16)); + snprintf(tmp_buf, sizeof(tmp_buf), "%c", (char)strtol(atts[i+1], NULL, 16)); php_wddx_process_data(user_data, tmp_buf, strlen(tmp_buf)); break; } @@ -801,7 +801,7 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X int i; if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp(atts[i], EL_VALUE) && atts[++i] && atts[i][0]) { + if (!strcmp(atts[i], EL_VALUE) && atts[i+1] && atts[i+1][0]) { ent.type = ST_BOOLEAN; SET_STACK_VARNAME; @@ -809,7 +809,7 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X INIT_PZVAL(ent.data); Z_TYPE_P(ent.data) = IS_BOOL; wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry)); - php_wddx_process_data(user_data, atts[i], strlen(atts[i])); + php_wddx_process_data(user_data, atts[i+1], strlen(atts[i+1])); break; } } @@ -842,9 +842,9 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X int i; if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) { + if (!strcmp(atts[i], EL_NAME) && atts[i+1] && atts[i+1][0]) { if (stack->varname) efree(stack->varname); - stack->varname = estrdup(atts[i]); + stack->varname = estrdup(atts[i+1]); break; } } @@ -857,11 +857,12 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X array_init(ent.data); if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp(atts[i], "fieldNames") && atts[++i] && atts[i][0]) { + if (!strcmp(atts[i], "fieldNames") && atts[i+1] && atts[i+1][0]) { zval *tmp; char *key; char *p1, *p2, *endp; + i++; endp = (char *)atts[i] + strlen(atts[i]); p1 = (char *)atts[i]; while ((p2 = php_memnstr(p1, ",", sizeof(",")-1, endp)) != NULL) { @@ -893,13 +894,13 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X ent.data = NULL; if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) { + if (!strcmp(atts[i], EL_NAME) && atts[i+1] && atts[i+1][0]) { st_entry *recordset; zval **field; if (wddx_stack_top(stack, (void**)&recordset) == SUCCESS && recordset->type == ST_RECORDSET && - zend_hash_find(Z_ARRVAL_P(recordset->data), (char*)atts[i], strlen(atts[i])+1, (void**)&field) == SUCCESS) { + zend_hash_find(Z_ARRVAL_P(recordset->data), (char*)atts[i+1], strlen(atts[i+1])+1, (void**)&field) == SUCCESS) { ent.data = *field; } -- cgit v1.2.1 From 33d0ef0fefed7b8eb958aa4f1b4e2e7602953d30 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 12 Sep 2016 20:12:41 -0700 Subject: Fix test --- ext/spl/tests/bug70068.phpt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/spl/tests/bug70068.phpt b/ext/spl/tests/bug70068.phpt index 92a38dfbd6..96b2fa808f 100644 --- a/ext/spl/tests/bug70068.phpt +++ b/ext/spl/tests/bug70068.phpt @@ -2,8 +2,13 @@ Bug #70068 (Dangling pointer in the unserialization of ArrayObject items) --FILE-- getMessage()."\n"; +} ?> OK --EXPECT-- +Error at offset 10 of 20 bytes OK \ No newline at end of file -- cgit v1.2.1 From 28f80baf3c53e267c9ce46a2a0fadbb981585132 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 12 Sep 2016 20:25:08 -0700 Subject: Fix bug #72293 - Heap overflow in mysqlnd related to BIT fields --- ext/mysqlnd/mysqlnd_wireprotocol.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 74c9724991..855a25cea1 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -1585,6 +1585,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zend_uchar * p = row_buffer->ptr; size_t data_size = row_buffer->app; zend_uchar * bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */ + const zend_uchar * const packet_end = (zend_uchar*) row_buffer->ptr + data_size; DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_aux"); @@ -1606,8 +1607,13 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, /* Don't reverse the order. It is significant!*/ zend_uchar *this_field_len_pos = p; /* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */ - unsigned long len = php_mysqlnd_net_field_length(&p); + const unsigned long len = php_mysqlnd_net_field_length(&p); + if (len != MYSQLND_NULL_LENGTH && ((p + len) > packet_end)) { + php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing "MYSQLND_SZ_T_SPEC + " bytes after end of packet", (p + len) - packet_end - 1); + DBG_RETURN(FAIL); + } if (copy_data == FALSE && current_field > start_field && last_field_was_string) { /* Normal queries: -- cgit v1.2.1 From 363c2524dd221d60697a16ea0b7561d557b65724 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 13 Sep 2016 10:43:51 +0200 Subject: fix C89 conformity --- Zend/zend_API.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 3e191b63eb..dce30da81a 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -655,7 +655,7 @@ END_EXTERN_C() #define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; } /* Check that returned string length fits int */ -#define RETVAL_STRINGL_CHECK(s, len, dup) \ +#define RETVAL_STRINGL_CHECK(s, len, dup) do { \ size_t __len = (len); \ if (UNEXPECTED(__len > INT_MAX)) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, max is %d", INT_MAX); \ @@ -664,8 +664,8 @@ END_EXTERN_C() } \ RETURN_FALSE; \ } \ - RETVAL_STRINGL((s), __len, (dup)) - + RETVAL_STRINGL((s), __len, (dup)) \ +} while (0) #define SET_VAR_STRING(n, v) { \ -- cgit v1.2.1 From 8fd0e0285f36514dab5603e05cb8efa7fea99c87 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 13 Sep 2016 10:50:44 +0200 Subject: missed semicolon --- Zend/zend_API.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index dce30da81a..53c1a4cbb5 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -664,7 +664,7 @@ END_EXTERN_C() } \ RETURN_FALSE; \ } \ - RETVAL_STRINGL((s), __len, (dup)) \ + RETVAL_STRINGL((s), __len, (dup)); \ } while (0) -- cgit v1.2.1