|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2017-08-12 18:05 UTC] admin at stickman dot hu
[2017-08-12 18:13 UTC] stas@php.net
-Type: Security
+Type: Bug
[2017-08-12 18:13 UTC] stas@php.net
[2017-08-12 18:47 UTC] nikic@php.net
-Status: Open
+Status: Closed
-Assigned To:
+Assigned To: nikic
[2017-08-12 18:47 UTC] nikic@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Nov 04 22:00:01 2025 UTC |
Description: ------------ This bug is related to #73029. When ArrayObject gets unserialized, it checks for the unserialized internal "array" variable to be either an array or an object. However, when it unserializes the additional properties, the already unserialized array may still turn into a reference. Then this internal array (now a reference) is cast to, and used as Z_OBJ, in spl_array_get_hash_table_ptr, when the object is used. The bug can be triggered both with a crafted serialized string, or simply serializing and unserializing a crafted object, e.g. by putting it into $_SESSION, or shared memory. It can also be triggered with a simple property read, if the ARRAY_AS_PROPS flags is set in a crafted serialized string. I think the error is both unserializing to a reference, and the absolutely unconditional "else" in spl_array_get_hash_table_ptr. - unserialize should make a defensive copy of 'array', like gmp does. - spl_array_get_hash_table_ptr should check if the array field is actually an object. Test script: --------------- class A{}; $a = new A(); $ao = new ArrayObject($a); $ao->reference_field = &$a; $ao_corrupted = unserialize(serialize($ao)); $ao_corrupted['x']; Expected result: ---------------- The code should not crash. Actual result: -------------- It throws segmentation fault with the following backtrace: #0 rebuild_object_properties (zobj=0x7ffff6477078) at /home/alex/projects/php/php-src/Zend/zend_object_handlers.c:80 #1 0x00000000004935be in spl_array_get_hash_table_ptr (intern=<optimized out>) at /home/alex/projects/php/php-src/ext/spl/spl_array.c:100 #2 spl_array_get_hash_table (intern=<optimized out>) at /home/alex/projects/php/php-src/ext/spl/spl_array.c:113 #3 spl_array_get_dimension_ptr (check_inherited=0, intern=<optimized out>, offset=0x7ffff646f1c0, type=<optimized out>) at /home/alex/projects/php/php-src/ext/spl/spl_array.c:296 #4 0x000000000048f56b in spl_array_read_dimension_ex (check_inherited=<optimized out>, object=0x7ffff64140a0, offset=0x7ffff646f1c0, type=0, rv=0x7ffff6414180) at /home/alex/projects/php/php-src/ext/spl/spl_array.c:430 #5 0x0000000000608fdb in zend_fetch_dimension_address_read (container=0x7ffff64140a0, dim=0x7ffff646f1c0, dim_type=16, type=0, support_strings=1, slow=1, result=<optimized out>) at /home/alex/projects/php/php-src/Zend/zend_execute.c:1880 #6 zend_fetch_dimension_address_read_R_slow (result=0x7ffff6414180, container=0x7ffff64140a0, dim=<optimized out>) at /home/alex/projects/php/php-src/Zend/zend_execute.c:1909 #7 0x00000000005d11f7 in ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER (execute_data=0x7ffff6414030) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:38121 #8 0x00000000005b0338 in execute_ex (ex=0x7ffff6414030) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:432 #9 0x00000000005b05bb in zend_execute (op_array=0x7ffff6481000, return_value=<optimized out>) at /home/alex/projects/php/php-src/Zend/zend_vm_execute.h:474 #10 0x000000000056e0a4 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/alex/projects/php/php-src/Zend/zend.c:1476 #11 0x000000000050f72e in php_execute_script (primary_file=0x7fffffffcb60) at /home/alex/projects/php/php-src/main/main.c:2537 #12 0x00000000006112e0 in do_cli (argc=2, argv=<optimized out>) at /home/alex/projects/php/php-src/sapi/cli/php_cli.c:993 #13 0x00000000006104a6 in main (argc=2, argv=0xa04480) at /home/alex/projects/php/php-src/sapi/cli/php_cli.c:1381