diff options
Diffstat (limited to 'ext/pcre/php_pcre.c')
-rw-r--r-- | ext/pcre/php_pcre.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 0e15793475..8d6b2eaffd 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1743,13 +1743,30 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return /* Go through the input array */ zend_hash_internal_pointer_reset(Z_ARRVAL_P(input)); - while(zend_hash_get_current_data(Z_ARRVAL_P(input), (void **)&entry) == SUCCESS) { + while (zend_hash_get_current_data(Z_ARRVAL_P(input), (void **)&entry) == SUCCESS) { + zend_bool is_copy; + zval *str; + + switch (Z_TYPE_PP(entry)) { + case IS_STRING: + is_copy = 0; + str = *entry; + break; + + default: + is_copy = 1; - convert_to_string_ex(entry); + ALLOC_ZVAL(str); + Z_ADDREF_PP(entry); /* the function below decreases the ref counting */ + COPY_PZVAL_TO_ZVAL(*str, *entry); + + convert_to_string(str); + break; + } /* Perform the match */ - count = pcre_exec(pce->re, extra, Z_STRVAL_PP(entry), - Z_STRLEN_PP(entry), 0, + count = pcre_exec(pce->re, extra, Z_STRVAL_P(str), + Z_STRLEN_P(str), 0, 0, offsets, size_offsets); /* Check for too many substrings condition. */ @@ -1762,25 +1779,30 @@ PHPAPI void php_pcre_grep_impl(pcre_cache_entry *pce, zval *input, zval *return } /* If the entry fits our requirements */ - if ((count > 0 && !invert) || - (count == PCRE_ERROR_NOMATCH && invert)) { - Z_ADDREF_PP(entry); + if ((count > 0 && !invert) || (count == PCRE_ERROR_NOMATCH && invert)) { + + if (!is_copy) { + SEPARATE_ARG_IF_REF(str); + } /* Add to return array */ switch (zend_hash_get_current_key(Z_ARRVAL_P(input), &string_key, &num_key, 0)) { case HASH_KEY_IS_STRING: zend_hash_update(Z_ARRVAL_P(return_value), string_key, - strlen(string_key)+1, entry, sizeof(zval *), NULL); + strlen(string_key)+1, &str, sizeof(zval *), NULL); break; case HASH_KEY_IS_LONG: - zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry, + zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, &str, sizeof(zval *), NULL); break; } + } else if (is_copy) { + zval_dtor(str); + FREE_ZVAL(str); } - + zend_hash_move_forward(Z_ARRVAL_P(input)); } zend_hash_internal_pointer_reset(Z_ARRVAL_P(input)); |