php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75393 Value not preserved when assign-adding an array to an object
Submitted: 2017-10-17 00:21 UTC Modified: 2019-02-14 11:27 UTC
From: bwoebi@php.net Assigned:
Status: Open Package: Scripting Engine problem
PHP Version: 7.0Git-2017-10-16 (Git) OS: Irrelevant
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: bwoebi@php.net
New email:
PHP Version: OS:

 

 [2017-10-17 00:21 UTC] bwoebi@php.net
Description:
------------
Assign-adding an array to an object leads to an use-after-free.

Test script:
---------------
$o = new stdClass;
$o += [];

Expected result:
----------------
Notice: Object of class stdClass could not be converted to int in - on line 1
Fatal error: Uncaught Error: Unsupported operand types in -:1
Stack trace:
#0 {main}
  thrown in - on line 1


Actual result:
--------------
Invalid read

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-10-17 00:21 UTC] bwoebi@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: bwoebi
 [2017-10-17 01:42 UTC] bwoebi@php.net
-Status: Assigned +Status: Open -Assigned To: bwoebi +Assigned To:
 [2017-10-17 01:42 UTC] bwoebi@php.net
Unassigning myself, there's a deeper rabbit hole than expected. The fix I attempted for the attached test to give the expected result is causing memory leaks in other tests.
Also, related issue: $rsrc += 1; leaks the resource.


--TEST--
Bug #75393 (Crash when assign-adding an array to an object)
--FILE--
<?php

try {
        $o = new stdClass;
        $o += [];
} catch (\Error $e) {
        var_dump($e->getMessage(), $o);
}

?>
--EXPECTF--

Notice: Object of class stdClass could not be converted to int in %s on line %d
string(25) "Unsupported operand types"
object(stdClass)#1 (0) {
}
 [2017-10-17 03:49 UTC] laruence@php.net
I can not reproduce this....
 [2017-10-17 03:53 UTC] laruence@php.net
this seems already be fixed: https://3v4l.org/oF3Al
 [2017-10-17 10:15 UTC] bwoebi@php.net
@laruence: It doesn't crash with master, yes. But it still does with PHP 7.0 and  7.1.

Also $o must not be int(1), but must be an instanceof stdClass afterwards.
 [2017-10-17 10:34 UTC] laruence@php.net
why not?

<?php
$o = new Stdclass();
var_dump((int)$o);

output:
PHP Notice:  Object of class stdClass could not be converted to int in /tmp/1.php on line 3
int(1)

and for:
$o += []

we preparing operands first, then trying to do add, then result in unsupported operand, which seems reasonable to me
 [2017-10-17 10:36 UTC] laruence@php.net
of course I also understand why it should be an stdclass instance, it also make sense, but it will make the codes complex, and this is really a rarely wrong case, so I think choose the easy way is a good chioce here.
 [2017-10-17 11:07 UTC] bwoebi@php.net
-Summary: Crash when assign-adding an array to an object +Summary: Value not preserved when assign-adding an array to an object -Package: Reproducible crash +Package: Scripting Engine problem
 [2017-10-17 11:07 UTC] bwoebi@php.net
Similarly:

php -r 'set_error_handler(function() { throw new \Exception; }); $a = "2"; $a .= "a"; try { $a+=1; } catch (\Exception $e) { } var_dump($a);'
int(3)

(instead of string(2) "2a")

(turns out the crash has already been fixed in the most recent git, but not yet in the last release. - renaming thus.)
 [2019-02-14 11:27 UTC] nikic@php.net
Triage: Segfault fixed in supported versions, but the incorrect type conversion still takes place.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue Jul 23 13:01:26 2019 UTC