]> granicus.if.org Git - php/commitdiff
Fix strtr() segfault
authorNikita Popov <nikic@php.net>
Fri, 9 May 2014 13:14:27 +0000 (15:14 +0200)
committerNikita Popov <nikic@php.net>
Fri, 9 May 2014 13:14:27 +0000 (15:14 +0200)
ext/standard/string.c
ext/standard/tests/strings/strtr_with_reference.phpt [new file with mode: 0644]

index ebd667956a91e2b384dc178aab7e93f1290ac1b4..bd1dc1ee741b9637fa008fc6c4f69937e1b829fa 100644 (file)
@@ -2855,17 +2855,11 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
                                if (len > slen - pos) continue;
                                entry = zend_hash_str_find(pats, key, len);
                                if (entry != NULL) {
-                                       if (UNEXPECTED(Z_TYPE_P(entry) != IS_STRING)) {
-                                               ZVAL_DUP(&tmp, entry);
-                                               convert_to_string(&tmp);
-                                               entry = &tmp;
-                                       }
-                                       smart_str_appendl(&result, Z_STRVAL_P(entry), Z_STRLEN_P(entry));
+                                       zend_string *str = zval_get_string(entry);
+                                       smart_str_appendl(&result, str->val, str->len);
                                        pos += len;
-                                       if (entry == &tmp) {
-                                               zval_dtor(&tmp);
-                                       }
                                        found = 1;
+                                       STR_RELEASE(str);
                                        break;
                                } 
                        } ZEND_HASH_FOREACH_END();
@@ -2886,17 +2880,11 @@ static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *
                        for (len = maxlen; len >= minlen; len--) {
                                entry = zend_hash_str_find(pats, key, len);
                                if (entry != NULL) {
-                                       if (UNEXPECTED(Z_TYPE_P(entry) != IS_STRING)) {
-                                               ZVAL_DUP(&tmp, entry);
-                                               convert_to_string(&tmp);
-                                               entry = &tmp;
-                                       }
-                                       smart_str_appendl(&result, Z_STRVAL_P(entry), Z_STRLEN_P(entry));
+                                       zend_string *str = zval_get_string(entry);
+                                       smart_str_appendl(&result, str->val, str->len);
                                        pos += len;
-                                       if (entry == &tmp) {
-                                               zval_dtor(&tmp);
-                                       }
                                        found = 1;
+                                       STR_RELEASE(str);
                                        break;
                                } 
                        }
diff --git a/ext/standard/tests/strings/strtr_with_reference.phpt b/ext/standard/tests/strings/strtr_with_reference.phpt
new file mode 100644 (file)
index 0000000..a28d1e7
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+strtr() with references
+--FILE--
+<?php
+
+$foo = 'foo';
+$arr = ['bar' => &$foo]; 
+var_dump(strtr('foobar', $arr));
+
+?>
+--EXPECT--
+string(6) "foofoo"