From: Nikita Popov Date: Mon, 2 Jan 2017 22:39:35 +0000 (+0100) Subject: Merge branch 'PHP-7.0' into PHP-7.1 X-Git-Tag: php-7.1.1RC1~27 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=737eb060dbbce6c77f499d800bacbfe6ef3e2087;p=php Merge branch 'PHP-7.0' into PHP-7.1 --- 737eb060dbbce6c77f499d800bacbfe6ef3e2087 diff --cc NEWS index 020bcc04e0,8711158387..c1fbefa669 --- a/NEWS +++ b/NEWS @@@ -63,9 -53,11 +63,12 @@@ PH . Fixed bug #70213 (Unserialize context shared on double class lookup). (Taoguang Chen) . Fixed bug #73154 (serialize object with __sleep function crash). (Nikita) + . Fixed bug #70490 (get_browser function is very slow). (Nikita) + . Fixed bug #73265 (Loading browscap.ini at startup causes high memory usage). + (Nikita) + . Add subject to mail log. (tomsommer) -- Zlib: +- Zlib . Fixed bug #73373 (deflate_add does not verify that output was not truncated). (Matt Bonneau) diff --cc ext/mysqlnd/mysqlnd_wireprotocol.c index b057a44e82,84f363b403..d6fa9017bd --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@@ -1468,7 -1443,13 +1468,7 @@@ php_mysqlnd_read_row_ex(MYSQLND_PFC * p zend_bool first_iteration = TRUE; DBG_ENTER("php_mysqlnd_read_row_ex"); - + - /* - * We're allocating 1 extra byte, as php_mysqlnd_rowp_read_text_protocol_aux - * needs to be able to add a terminating \0 for atoi/atof. - */ - prealloc_more_bytes++; - /* To ease the process the server splits everything in packets up to 2^24 - 1. Even in the case the payload is evenly divisible by this value, the last diff --cc ext/standard/browscap.c index a52ed2501f,71491bcb45..c913cc8c97 --- a/ext/standard/browscap.c +++ b/ext/standard/browscap.c @@@ -50,30 -69,91 +69,91 @@@ ZEND_DECLARE_MODULE_GLOBALS(browscap /* OBJECTS_FIXME: This whole extension needs going through. The use of objects looks pretty broken here */ - static void browscap_entry_dtor_request(zval *zvalue) /* {{{ */ + static void browscap_entry_dtor(zval *zvalue) { - if (Z_TYPE_P(zvalue) == IS_ARRAY) { - zend_hash_destroy(Z_ARRVAL_P(zvalue)); - efree(Z_ARR_P(zvalue)); - } else if (Z_TYPE_P(zvalue) == IS_STRING) { - zend_string_release(Z_STR_P(zvalue)); + browscap_entry *entry = Z_PTR_P(zvalue); + zend_string_release(entry->pattern); + if (entry->parent) { + zend_string_release(entry->parent); } + efree(entry); } - /* }}} */ - static void browscap_entry_dtor_persistent(zval *zvalue) /* {{{ */ { - if (Z_TYPE_P(zvalue) == IS_ARRAY) { - zend_hash_destroy(Z_ARRVAL_P(zvalue)); - free(Z_ARR_P(zvalue)); - } else if (Z_TYPE_P(zvalue) == IS_STRING) { - zend_string_release(Z_STR_P(zvalue)); + static void browscap_entry_dtor_persistent(zval *zvalue) + { + browscap_entry *entry = Z_PTR_P(zvalue); + zend_string_release(entry->pattern); + if (entry->parent) { + zend_string_release(entry->parent); } + pefree(entry, 1); + } + + static inline zend_bool is_placeholder(char c) { + return c == '?' || c == '*'; + } + + /* Length of prefix not containing any wildcards */ + static uint8_t browscap_compute_prefix_len(zend_string *pattern) { + size_t i; + for (i = 0; i < ZSTR_LEN(pattern); i++) { + if (is_placeholder(ZSTR_VAL(pattern)[i])) { + break; + } + } + return MIN(i, UINT8_MAX); + } + + static size_t browscap_compute_contains( + zend_string *pattern, size_t start_pos, + uint16_t *contains_start, uint8_t *contains_len) { + size_t i = start_pos; + /* Find first non-placeholder character after prefix */ + for (; i < ZSTR_LEN(pattern); i++) { + if (!is_placeholder(ZSTR_VAL(pattern)[i])) { + /* Skip the case of a single non-placeholder character. + * Let's try to find something longer instead. */ + if (i + 1 < ZSTR_LEN(pattern) && + !is_placeholder(ZSTR_VAL(pattern)[i + 1])) { + break; + } + } + } + *contains_start = i; + + /* Find first placeholder character after that */ + for (; i < ZSTR_LEN(pattern); i++) { + if (is_placeholder(ZSTR_VAL(pattern)[i])) { + break; + } + } + *contains_len = MIN(i - *contains_start, UINT8_MAX); + return i; + } + + /* Length of regex, including escapes, anchors, etc. */ + static size_t browscap_compute_regex_len(zend_string *pattern) { + size_t i, len = ZSTR_LEN(pattern); + for (i = 0; i < ZSTR_LEN(pattern); i++) { + switch (ZSTR_VAL(pattern)[i]) { + case '*': + case '.': + case '\\': + case '(': + case ')': + case '~': + case '+': + len++; + break; + } + } + + return len + sizeof("~^$~")-1; } - /* }}} */ - static void convert_browscap_pattern(zval *pattern, int persistent) /* {{{ */ + static zend_string *browscap_convert_pattern(zend_string *pattern, int persistent) /* {{{ */ { - int i, j=0; + size_t i, j=0; char *t; zend_string *res; char *lc_pattern; @@@ -220,7 -392,8 +392,8 @@@ static void php_browscap_parser_cb(zva static int browscap_read_file(char *filename, browser_data *browdata, int persistent) /* {{{ */ { - zend_file_handle fh = {{0}}; + zend_file_handle fh; + browscap_parser_ctx ctx = {0}; if (filename == NULL || filename[0] == '\0') { return FAILURE;