summaryrefslogtreecommitdiff
path: root/ext/pcre/php_pcre.c
diff options
context:
space:
mode:
authorNuno Lopes <nlopess@php.net>2008-08-14 13:12:42 +0000
committerNuno Lopes <nlopess@php.net>2008-08-14 13:12:42 +0000
commit31c657b3bb8bae5c9b09785740102a1464af5029 (patch)
treeb8ccda76dd9b17559882c65a516dfea33f07fc72 /ext/pcre/php_pcre.c
parent878946a34f4226f4a98eb361508680e51e8f34de (diff)
downloadphp-git-31c657b3bb8bae5c9b09785740102a1464af5029.tar.gz
Fixed bug #44925 (preg_grep() modifies input array)
Diffstat (limited to 'ext/pcre/php_pcre.c')
-rw-r--r--ext/pcre/php_pcre.c42
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));