summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancois Laupretre <francois@tekwire.net>2016-02-12 00:01:59 +0100
committerNikita Popov <nikic@php.net>2016-02-14 13:18:23 +0100
commitbe607e724c69c92f8cda72a45a13a26e7c439aec (patch)
tree1acbbb94bfadf0c3c9c242bed73f28ce50d867af
parentd10911afde4dfb9d66c60a05b387491eb6c70236 (diff)
downloadphp-git-be607e724c69c92f8cda72a45a13a26e7c439aec.tar.gz
Fix bug #71572
Discussed on the internals list as part of http://markmail.org/message/fa625yc2eegk2dio.
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug71572.phpt27
-rw-r--r--Zend/zend_execute.c42
3 files changed, 57 insertions, 14 deletions
diff --git a/NEWS b/NEWS
index 0ae66b8f34..b0ee6b88e5 100644
--- 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
index 0000000000..4a823ec72f
--- /dev/null
+++ b/Zend/tests/bug71572.phpt
@@ -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
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 63fc5e6366..69326ab4dc 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -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 {