Bug #71572 [Com]: String offset assignment from an empty string inserts null byte

From: Date: Fri, 12 Feb 2016 08:53:48 +0000
Subject: Bug #71572 [Com]: String offset assignment from an empty string inserts null byte
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-199172@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=71572&edit=1

 ID:                 71572
 Comment by:         salsi at icosaedro dot it
 Reported by:        francois@php.net
 Summary:            String offset assignment from an empty string
                     inserts null byte
 Status:             Assigned
 Type:               Bug
 Package:            Strings related
 Operating System:   Any
 PHP Version:        7.0.3
 Assigned To:        francois
 Block user comment: N
 Private report:     N

 New Comment:

My survey of several oddities and undefined behaviors in string single-byte assignment which are
strictly relates to this same topic I have collected from the discussions of these days that should
be addressed as a whole in some consistent way:

<?php

// Set char in string oddities (PHP 5.6.3, PHP 7.1.0-dev).
error_reporting(-1);

// Replacing a single byte.
$s = "abc";
$s[1] = "x";
echo "replace byte: ", rawurlencode($s), "\n"; // -> axc (expected)

// Set single byte with empty replacement string (undefined behavior).
// https://bugs.php.net/bug.php?id=71572
// Expected: some error.
// Actual: replaces with byte 0.
$s = "abc";
$s[1] = ""; // empty string
echo "set empty byte: ", rawurlencode($s), "\n"; // --> a%00c

// Set single byte with 2+ bytes long replacement string (undefined behavior).
// Expected: some error.
// Actual: replaces with the first byte of the replacement string.
$s = "abc";
$s[1] = "xyz";
echo "set multiple bytes: ", rawurlencode($s), "\n"; // --> axc

// Set single byte on empty string (undefined behavior).
// Expected: some error because undefined behavior (no char to replace at
// the given offset).
// Actual: type switch to array.
$s = ""; // Empty string
$s[1] = "z";
echo "set on empty string: "; var_dump($s); // -> array(1) { [1]=>string(1)
"z" }

// Append to empty string.
// Expected: append "z" to empty string resulting in "z".
// Actual: type switch to array.
$s = "";
$s[] = 'z';
echo "append on empty string: "; var_dump($s); // -> array(1) { [0]=>string(1)
"z" }

// Append on non-empty string.
// Expected: append "z" to "a" resulting in "az".
// Actual: fatal error.
$s = "a";
$s[] = 'z'; // -> Fatal error : [] operator not supported for strings
?>

In my opinion, the simplest thing to do is to define the "string single-byte assignment"
as the replacement of the existing byte at the given offset with the first byte of the replacement
string, any other case causing E_WARNING; appending $s[] = ... not allowed (there is the . operator
already); unexpected conversion to array absolutely to fix!


Previous Comments:
------------------------------------------------------------------------
[2016-02-11 22:12:48] francois@php.net

Description:
------------
When assigning to a string offset from an empty string, the corresponding byte is set to a null
value.

In zend_assign_to_string_offset(), the length of the input string should be checked. If 0, a warning
should be raised and the string shouldn't be modified.


Test script:
---------------
$str = "abc";
$str{0} = "";
var_dump($str);


Expected result:
----------------
PHP Fatal error:  Uncaught Error: Cannot assign an empty string to a string offset in ...


Actual result:
--------------
string(3) "bc" (read as "\0bc")



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=71572&edit=1


Thread (3 messages)

« previous php.bugs (#199172) next »