diff options
author | Francois Laupretre <francois@tekwire.net> | 2016-02-12 00:01:59 +0100 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2016-02-14 13:18:23 +0100 |
commit | be607e724c69c92f8cda72a45a13a26e7c439aec (patch) | |
tree | 1acbbb94bfadf0c3c9c242bed73f28ce50d867af | |
parent | d10911afde4dfb9d66c60a05b387491eb6c70236 (diff) | |
download | php-git-be607e724c69c92f8cda72a45a13a26e7c439aec.tar.gz |
Fix bug #71572
Discussed on the internals list as part of
http://markmail.org/message/fa625yc2eegk2dio.
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug71572.phpt | 27 | ||||
-rw-r--r-- | Zend/zend_execute.c | 42 |
3 files changed, 57 insertions, 14 deletions
@@ -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 { |