]> granicus.if.org Git - php/commitdiff
Fix bug #71572
authorFrancois Laupretre <francois@tekwire.net>
Thu, 11 Feb 2016 23:01:59 +0000 (00:01 +0100)
committerNikita Popov <nikic@php.net>
Sun, 14 Feb 2016 12:18:23 +0000 (13:18 +0100)
Discussed on the internals list as part of
http://markmail.org/message/fa625yc2eegk2dio.

NEWS
Zend/tests/bug71572.phpt [new file with mode: 0644]
Zend/zend_execute.c

diff --git a/NEWS b/NEWS
index 0ae66b8f34412f76c07b12a4004d36ba43ac0b4c..b0ee6b88e509e6bca5c1413f45652a697f433b72 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP                                                                        NEWS
 - Core:
   . Fixed bug #62210 (Exceptions can leak temporary variables). (Dmitry, Bob)
   . Fixed bug #69989 (Generators don't participate in cycle GC). (Nikita)
+  . Fixed buf #71572 (String offset assignment from an empty string inserts
+    null byte). (Francois)
   . Implemented the RFC `Support Class Constant Visibility`. (Sean DuBois,
     Reeze Xia, Dmitry)
   . Added void return type. (Andrea)
diff --git a/Zend/tests/bug71572.phpt b/Zend/tests/bug71572.phpt
new file mode 100644 (file)
index 0000000..4a823ec
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Bug #71572: String offset assignment from an empty string inserts null byte
+--FILE--
+<?php
+
+$str = "abc";
+var_dump($str{0} = "");
+var_dump($str{1} = "");
+var_dump($str{3} = "");
+var_dump($str{10} = "");
+var_dump($str);
+?>
+==DONE==
+--EXPECTF--
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+string(3) "abc"
+==DONE==
\ No newline at end of file
index 63fc5e63667429e1e5dab286b9b20b1a5598107b..69326ab4dc4ab8ed321b40c0e144f7a70a8abc42 100644 (file)
@@ -1169,8 +1169,11 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *
 static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result)
 {
        zend_string *old_str;
+       zend_uchar c;
+       size_t string_len;
 
        if (offset < 0) {
+               /* Error on negative offset */
                zend_error(E_WARNING, "Illegal string offset:  " ZEND_LONG_FMT, offset);
                zend_string_release(Z_STR_P(str));
                if (result) {
@@ -1179,8 +1182,31 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu
                return;
        }
 
+       if (Z_TYPE_P(value) != IS_STRING) {
+               /* Convert to string, just the time to pick the 1st byte */
+               zend_string *tmp = zval_get_string(value);
+
+               string_len = ZSTR_LEN(tmp);
+               c = (zend_uchar)ZSTR_VAL(tmp)[0];
+               zend_string_release(tmp);
+       } else {
+               string_len = Z_STRLEN_P(value);
+               c = (zend_uchar)Z_STRVAL_P(value)[0];
+       }
+
+       if (string_len == 0) {
+               /* Error on empty input string */
+               zend_error(E_WARNING, "Cannot assign an empty string to a string offset");
+               zend_string_release(Z_STR_P(str));
+               if (result) {
+                       ZVAL_NULL(result);
+               }
+               return;
+       }
+
        old_str = Z_STR_P(str);
        if ((size_t)offset >= Z_STRLEN_P(str)) {
+               /* Extend string if needed */
                zend_long old_len = Z_STRLEN_P(str);
                Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
                Z_TYPE_INFO_P(str) = IS_STRING_EX;
@@ -1191,23 +1217,11 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu
                Z_TYPE_INFO_P(str) = IS_STRING_EX;
        }
 
-       if (Z_TYPE_P(value) != IS_STRING) {
-               zend_string *tmp = zval_get_string(value);
-
-               Z_STRVAL_P(str)[offset] = ZSTR_VAL(tmp)[0];
-               zend_string_release(tmp);
-       } else {
-               Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
-       }
-       /*
-        * the value of an assignment to a string offset is undefined
-       T(result->u.var).var = &T->str_offset.str;
-       */
+       Z_STRVAL_P(str)[offset] = c;
 
        zend_string_release(old_str);
        if (result) {
-               zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
-
+               /* Return the new character */
                if (CG(one_char_string)[c]) {
                        ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
                } else {