From bfe3f934a37ec7e2abcef286294e52abab3e844a Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 7 Jan 2020 21:51:34 +0100 Subject: [PATCH] Add warning and convert to exception in string offset assignment: Convert the empty string assignment to an Error as per RFC [1] Add a warning that only the first byte will be assigned to the offset if provided a needle that is longer than one byte. [1] https://wiki.php.net/rfc/engine_warnings --- Zend/tests/bug71572.phpt | 41 ++++++++++++++++++------------ Zend/tests/indexing_001.phpt | 8 +++--- Zend/tests/str_offset_004.phpt | 2 ++ Zend/zend_execute.c | 18 ++++++++----- ext/opcache/jit/zend_jit_helpers.c | 17 ++++++++----- tests/lang/bug22592.phpt | 2 ++ 6 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Zend/tests/bug71572.phpt b/Zend/tests/bug71572.phpt index 063a98fcb917e..f4079e55f89a0 100644 --- a/Zend/tests/bug71572.phpt +++ b/Zend/tests/bug71572.phpt @@ -4,22 +4,31 @@ Bug #71572: String offset assignment from an empty string inserts null byte getMessage() . \PHP_EOL; +} +try { + var_dump($str[1] = ""); +} catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; +} +try { + var_dump($str[3] = ""); +} catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; +} +try { + var_dump($str[10] = ""); +} catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; +} var_dump($str); ?> ---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 +--EXPECT-- +Cannot assign an empty string to a string offset +Cannot assign an empty string to a string offset +Cannot assign an empty string to a string offset +Cannot assign an empty string to a string offset string(3) "abc" diff --git a/Zend/tests/indexing_001.phpt b/Zend/tests/indexing_001.phpt index 453b5ca86f80d..5a5fbef054631 100644 --- a/Zend/tests/indexing_001.phpt +++ b/Zend/tests/indexing_001.phpt @@ -51,8 +51,6 @@ foreach ($testvalues as $testvalue) { var_dump ($testvalue); } - -echo "\nDone"; ?> --EXPECTF-- *** Indexing - Testing value assignment with key *** @@ -80,11 +78,15 @@ array(1) { Warning: Illegal string offset 'foo' in %s on line %d Warning: Array to string conversion in %s on line %d + +Warning: Only the first byte will be assigned to the string offset in %s on line %d string(1) "A" Warning: Illegal string offset 'foo' in %s on line %d Warning: Array to string conversion in %s on line %d + +Warning: Only the first byte will be assigned to the string offset in %s on line %d string(1) "A" Cannot use a scalar value as an array float(0.1) @@ -187,5 +189,3 @@ array(1) { int(1) } } - -Done diff --git a/Zend/tests/str_offset_004.phpt b/Zend/tests/str_offset_004.phpt index 435ab235fa61d..a0f89e9186129 100644 --- a/Zend/tests/str_offset_004.phpt +++ b/Zend/tests/str_offset_004.phpt @@ -45,5 +45,7 @@ Warning: Illegal string offset: -20 in %sstr_offset_004.php on line %d string(15) "abCZefghijPQmno" string(15) "AbCZefghijPQmno" string(21) "AbCZefghijPQmno N" + +Warning: Only the first byte will be assigned to the string offset in %s on line %d string(21) "AbCZefghijPQmno UN" string(21) "AbCZefghijPQmno nUN" diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 4821e2a1e4286..cae63b06c3eab 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1597,14 +1597,18 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, 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"); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_NULL(EX_VAR(opline->result.var)); + + if (string_len != 1) { + if (string_len == 0) { + /* Error on empty input string */ + zend_throw_error(NULL, "Cannot assign an empty string to a string offset"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + return; } - return; + + zend_error(E_WARNING, "Only the first byte will be assigned to the string offset"); } if (offset < 0) { /* Handle negative offset */ diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index e2ba36c9eee74..c04985110c5fd 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -895,13 +895,18 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, 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"); - if (result) { - ZVAL_NULL(result); + + if (string_len != 1) { + if (string_len == 0) { + /* Error on empty input string */ + zend_throw_error(NULL, "Cannot assign an empty string to a string offset"); + if (result) { + ZVAL_NULL(result); + } + return; } - return; + + zend_error(E_WARNING, "Only the first byte will be assigned to the string offset"); } if (offset < 0) { /* Handle negative offset */ diff --git a/tests/lang/bug22592.phpt b/tests/lang/bug22592.phpt index 4614efc1692b7..6999c0bccf2b5 100644 --- a/tests/lang/bug22592.phpt +++ b/tests/lang/bug22592.phpt @@ -39,9 +39,11 @@ var_dump($result); string(5) "* *-*" string(7) "* *-* *" string(7) "*4*-* *" +[Only the first byte will be assigned to the string offset] string(7) "*4*s* *" string(8) "*4*s* *0" string(8) "*-*-* *0" +[Only the first byte will be assigned to the string offset] string(8) "*-*s*s*0" string(8) "4-4s4s*0" string(9) "4-4s4s505"