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

 ID:                 60701
 Comment by:         hans at rakers dot org
 Reported by:        daan at react dot com
 Summary:            __toString() which stores $this reference triggers
                     segfault
 Status:             Open
 Type:               Bug
 Package:            Class/Object related
 Operating System:   CentOS
 PHP Version:        5.3.8
 Block user comment: N
 Private report:     N

 New Comment:

This bug is caused by zend_std_cast_object_tostring() not checking the refcount 
of readobj when readobj==writeobj. It calls INIT_PZVAL(writeobj) without 
checking the refcount first, causing any further references to this zval to get 
corrupted (in this case, the 'test' property of StringableObject).

My patch against 5.3 is attached.


Previous Comments:
------------------------------------------------------------------------
[2012-01-10 19:22:39] sjon at hortensius dot net

This bug is not reproducible when php is compiled with enable-debug. It is 
however reproducible in other PHP versions, such as 5.3.7/5.3.6/5.3.5

------------------------------------------------------------------------
[2012-01-10 16:43:17] daan at react dot com

Description:
------------
A simple object construction where a __toString() stores $this, will trigger a 
segfault during garbage collection at the end of the request.

Probably related bug: https://bugs.php.net/bug.php?id=60598
Is a distilled version of this bug: https://bugs.php.net/bug.php?id=60457

Test script:
---------------
<?php
class Container
{
        public function getObject()
        {
                $this->object = new StringableObject();

                return $this->object;
        }

        // This destructor is required to exist to trigger the segfault
        public function __destruct()
        {
        }
}

class StringableObject
{
        public function __toString()
        {
                $this->test = $this;

                return '';
        }
}

$container = new Container();
$object = $container->getObject();

// Any kind of function which triggers a 'to string' object conversion
// Casting $object with (string) will circumvent the problem
echo trim($object);
// Another call is required to corrupt heap
echo trim('test');


Expected result:
----------------
test

Actual result:
--------------
Segfault

gdb backtrace (with commandline PHP with build tag ZEND_DEBUG_OBJECTS)

[Thread debugging using libthread_db enabled]
Allocated object id #1
Allocated object id #2
Increased refcount of object id #2
Decreased refcount of object id #2
testIncreased refcount of object id #1
Decreased refcount of object id #1
Deallocated object id #1

Program received signal SIGSEGV, Segmentation fault.
0x00000000006d4c69 in gc_zval_possible_root (zv=0x1023e40) at /home/sjon/php-
debug/php-5.3.8/Zend/zend_gc.c:143
143            GC_ZOBJ_CHECK_POSSIBLE_ROOT(zv);
(gdb) bt
#0  0x00000000006d4c69 in gc_zval_possible_root (zv=0x1023e40) at 
/home/sjon/php-debug/php-5.3.8/Zend/zend_gc.c:143
#1  0x00000000006c4ad8 in zend_hash_destroy (ht=0x10266d0) at /home/sjon/php-
debug/php-5.3.8/Zend/zend_hash.c:529
#2  0x00000000006d6009 in zend_object_std_dtor (object=0x1023dc8) at 
/home/sjon/php-debug/php-5.3.8/Zend/zend_objects.c:45
#3  0x00000000006d6029 in zend_objects_free_object_storage (object=0x1023dc8) 
at 
/home/sjon/php-debug/php-5.3.8/Zend/zend_objects.c:126
#4  0x00000000006da037 in zend_objects_store_del_ref_by_handle_ex (handle=2, 
handlers=<optimized out>) at /home/sjon/php-debug/php-
5.3.8/Zend/zend_objects_API.c:220
#5  0x00000000006da053 in zend_objects_store_del_ref (zobject=0x1022350) at 
/home/sjon/php-debug/php-5.3.8/Zend/zend_objects_API.c:172
#6  0x00000000006a9571 in _zval_dtor (zvalue=0x1022350) at /home/sjon/php-
debug/php-5.3.8/Zend/zend_variables.h:35
#7  _zval_ptr_dtor (zval_ptr=<optimized out>) at /home/sjon/php-debug/php-
5.3.8/Zend/zend_execute_API.c:447
#8  0x00000000006c3645 in zend_hash_apply_deleter (ht=0xe33188, p=0x1026728) at 
/home/sjon/php-debug/php-5.3.8/Zend/zend_hash.c:612
#9  0x00000000006c4f81 in zend_hash_reverse_apply (ht=0xe33188, 
apply_func=0x6a9430 <zval_call_destructor>) at /home/sjon/php-debug/php-
5.3.8/Zend/zend_hash.c:762
#10 0x00000000006a9921 in shutdown_destructors () at /home/sjon/php-debug/php-
5.3.8/Zend/zend_execute_API.c:226
#11 0x00000000006b7747 in zend_call_destructors () at /home/sjon/php-debug/php-
5.3.8/Zend/zend.c:875
#12 0x00000000006651fd in php_request_shutdown (dummy=<optimized out>) at 
/home/sjon/php-debug/php-5.3.8/main/main.c:1594
#13 0x000000000042d105 in main (argc=2, argv=0x7fffffffebb8) at /home/sjon/php-
debug/php-5.3.8/sapi/cli/php_cli.c:1363
(gdb) frame 2
#2  0x00000000006d6009 in zend_object_std_dtor (object=0x1023dc8) at 
/home/sjon/php-debug/php-5.3.8/Zend/zend_objects.c:45
45            zend_hash_destroy(object->properties);
(gdb) print object->ce->name
$1 = 0x1025af0 "StringableObject" 
(gdb) frame 1
#1  0x00000000006c4ad8 in zend_hash_destroy (ht=0x10266d0) at /home/sjon/php-
debug/php-5.3.8/Zend/zend_hash.c:529
529                ht->pDestructor(q->pData);
(gdb) print_ht ht
[0x010266d0] {
  "test\0" => [0x01023e40] (refcount=-1) object
Program received signal SIGSEGV, Segmentation fault.
0x00000000006da0a4 in zend_object_store_get_object (zobject=0x1023e40) at 
/home/sjon/php-debug/php-5.3.8/Zend/zend_objects_API.c:272
272        return EG(objects_store).object_buckets[handle].bucket.obj.object;
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on".
Evaluation of the expression containing the function
(zend_objects_get_address) will be abandoned.
When the function is done executing, GDB will silently stop.
(gdb) 



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



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

Reply via email to