Skip to content

Commit be607e7

Browse files
flaupretrenikic
authored andcommitted
Fix bug #71572
Discussed on the internals list as part of http://markmail.org/message/fa625yc2eegk2dio.
1 parent d10911a commit be607e7

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- Core:
66
. Fixed bug #62210 (Exceptions can leak temporary variables). (Dmitry, Bob)
77
. Fixed bug #69989 (Generators don't participate in cycle GC). (Nikita)
8+
. Fixed buf #71572 (String offset assignment from an empty string inserts
9+
null byte). (Francois)
810
. Implemented the RFC `Support Class Constant Visibility`. (Sean DuBois,
911
Reeze Xia, Dmitry)
1012
. Added void return type. (Andrea)

Zend/tests/bug71572.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #71572: String offset assignment from an empty string inserts null byte
3+
--FILE--
4+
<?php
5+
6+
$str = "abc";
7+
var_dump($str{0} = "");
8+
var_dump($str{1} = "");
9+
var_dump($str{3} = "");
10+
var_dump($str{10} = "");
11+
var_dump($str);
12+
?>
13+
==DONE==
14+
--EXPECTF--
15+
Warning: Cannot assign an empty string to a string offset in %s on line %d
16+
NULL
17+
18+
Warning: Cannot assign an empty string to a string offset in %s on line %d
19+
NULL
20+
21+
Warning: Cannot assign an empty string to a string offset in %s on line %d
22+
NULL
23+
24+
Warning: Cannot assign an empty string to a string offset in %s on line %d
25+
NULL
26+
string(3) "abc"
27+
==DONE==

Zend/zend_execute.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,8 +1169,11 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *
11691169
static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result)
11701170
{
11711171
zend_string *old_str;
1172+
zend_uchar c;
1173+
size_t string_len;
11721174

11731175
if (offset < 0) {
1176+
/* Error on negative offset */
11741177
zend_error(E_WARNING, "Illegal string offset: " ZEND_LONG_FMT, offset);
11751178
zend_string_release(Z_STR_P(str));
11761179
if (result) {
@@ -1179,8 +1182,31 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu
11791182
return;
11801183
}
11811184

1185+
if (Z_TYPE_P(value) != IS_STRING) {
1186+
/* Convert to string, just the time to pick the 1st byte */
1187+
zend_string *tmp = zval_get_string(value);
1188+
1189+
string_len = ZSTR_LEN(tmp);
1190+
c = (zend_uchar)ZSTR_VAL(tmp)[0];
1191+
zend_string_release(tmp);
1192+
} else {
1193+
string_len = Z_STRLEN_P(value);
1194+
c = (zend_uchar)Z_STRVAL_P(value)[0];
1195+
}
1196+
1197+
if (string_len == 0) {
1198+
/* Error on empty input string */
1199+
zend_error(E_WARNING, "Cannot assign an empty string to a string offset");
1200+
zend_string_release(Z_STR_P(str));
1201+
if (result) {
1202+
ZVAL_NULL(result);
1203+
}
1204+
return;
1205+
}
1206+
11821207
old_str = Z_STR_P(str);
11831208
if ((size_t)offset >= Z_STRLEN_P(str)) {
1209+
/* Extend string if needed */
11841210
zend_long old_len = Z_STRLEN_P(str);
11851211
Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
11861212
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
11911217
Z_TYPE_INFO_P(str) = IS_STRING_EX;
11921218
}
11931219

1194-
if (Z_TYPE_P(value) != IS_STRING) {
1195-
zend_string *tmp = zval_get_string(value);
1196-
1197-
Z_STRVAL_P(str)[offset] = ZSTR_VAL(tmp)[0];
1198-
zend_string_release(tmp);
1199-
} else {
1200-
Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
1201-
}
1202-
/*
1203-
* the value of an assignment to a string offset is undefined
1204-
T(result->u.var).var = &T->str_offset.str;
1205-
*/
1220+
Z_STRVAL_P(str)[offset] = c;
12061221

12071222
zend_string_release(old_str);
12081223
if (result) {
1209-
zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
1210-
1224+
/* Return the new character */
12111225
if (CG(one_char_string)[c]) {
12121226
ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
12131227
} else {

0 commit comments

Comments
 (0)