The test segfaults here. And Valgrind shows this: ==21439== Invalid read of size 8 ==21439== at 0x8EDC69: _php_stream_write (streams.c:1085) ==21439== by 0x826C0A: zif_fwrite (file.c:1294) ==21439== by 0x97C392: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:320) ==21439== by 0x98092B: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:1634) ==21439== by 0x97B84E: execute (zend_vm_execute.h:107) ==21439== by 0x947F26: zend_execute_scripts (zend.c:1194) ==21439== by 0x8D2DC2: php_execute_script (main.c:2275) ==21439== by 0xA2C00D: main (php_cli.c:1193) ==21439== Address 0xa73d7d0 is 0 bytes inside a block of size 240 free'd ==21439== at 0x4C2599C: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==21439== by 0x8EC55E: _php_stream_free (streams.c:442) ==21439== by 0x8FD3CF: _php_stream_xport_create (transports.c:83) ==21439== by 0x8327BB: php_fsockopen_stream (fsock.c:79) ==21439== by 0x832A54: zif_pfsockopen (fsock.c:130) ==21439== by 0x97C392: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:320) ==21439== by 0x98092B: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:1634) ==21439== by 0x97B84E: execute (zend_vm_execute.h:107) ==21439== by 0x947F26: zend_execute_scripts (zend.c:1194) ==21439== by 0x8D2DC2: php_execute_script (main.c:2275) ==21439== by 0xA2C00D: main (php_cli.c:1193)
....... ==21439== Process terminating with default action of signal 11 (SIGSEGV) ==21439== Access not within mapped region at address 0x0 ==21439== at 0x8FE617: php_sockop_write (xp_socket.c:60) ==21439== by 0x8ED984: _php_stream_write_buffer (streams.c:981) ==21439== by 0x8EDCBC: _php_stream_write (streams.c:1092) ==21439== by 0x826C0A: zif_fwrite (file.c:1294) ==21439== by 0x97C392: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:320) ==21439== by 0x98092B: ZEND_DO_FCALL_SPEC_CONST_HANDLER (zend_vm_execute.h:1634) ==21439== by 0x97B84E: execute (zend_vm_execute.h:107) ==21439== by 0x947F26: zend_execute_scripts (zend.c:1194) ==21439== by 0x8D2DC2: php_execute_script (main.c:2275) ==21439== by 0xA2C00D: main (php_cli.c:1193) ==21439== If you believe this happened as a result of a stack ==21439== overflow in your program's main thread (unlikely but ==21439== possible), you can try to increase the size of the ==21439== main thread stack using the --main-stacksize= flag. ==21439== The main thread stack size used in this run was 8388608. On 05/01/2011 07:57 AM, Gustavo André dos Santos Lopes wrote:
cataphract Sun, 01 May 2011 03:57:01 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=310681 Log: - Fixed bug #54623 (Segfault when when writing to a persistent socket after closing a copy of the socket). Bug: http://bugs.php.net/54623 (Assigned) Segmentation fault after writing to first socket after closing of second socket Changed paths: U php/php-src/branches/PHP_5_3/NEWS A php/php-src/branches/PHP_5_3/ext/standard/tests/streams/bug54623.phpt U php/php-src/branches/PHP_5_3/main/streams/streams.c A php/php-src/trunk/ext/standard/tests/streams/bug54623.phpt U php/php-src/trunk/main/streams/streams.c Modified: php/php-src/branches/PHP_5_3/NEWS =================================================================== --- php/php-src/branches/PHP_5_3/NEWS 2011-05-01 01:14:38 UTC (rev 310680) +++ php/php-src/branches/PHP_5_3/NEWS 2011-05-01 03:57:01 UTC (rev 310681) @@ -109,6 +109,10 @@ . Fixed bug #54281 (Crash in non-initialized RecursiveIteratorIterator). (Felipe) +- Streams: + . Fixed bug #54623 (Segfault when when writing to a persistent socket after + closing a copy of the socket). (Gustavo) + 17 Mar 2011, PHP 5.3.6 - Upgraded bundled Sqlite3 to version 3.7.4. (Ilia) - Upgraded bundled PCRE to version 8.11. (Ilia) Added: php/php-src/branches/PHP_5_3/ext/standard/tests/streams/bug54623.phpt =================================================================== --- php/php-src/branches/PHP_5_3/ext/standard/tests/streams/bug54623.phpt (rev 0) +++ php/php-src/branches/PHP_5_3/ext/standard/tests/streams/bug54623.phpt 2011-05-01 03:57:01 UTC (rev 310681) @@ -0,0 +1,17 @@ +--TEST-- +Bug #54623: Segfault when when writing to a persistent socket after closing a copy of the socket +--FILE-- +<?php +$sock = pfsockopen('udp://127.0.0.1', '63844'); +var_dump((int)$sock); +fwrite($sock, "1"); +$sock2 = pfsockopen('udp://127.0.0.1', '63844'); +var_dump((int)$sock2); +fwrite($sock2, "2"); +fclose($sock2); +fwrite($sock, "3"); +--EXPECTF-- +int(%d) +int(%d) + +Warning: fwrite(): %d is not a valid stream resource in %s on line %d Modified: php/php-src/branches/PHP_5_3/main/streams/streams.c =================================================================== --- php/php-src/branches/PHP_5_3/main/streams/streams.c 2011-05-01 01:14:38 UTC (rev 310680) +++ php/php-src/branches/PHP_5_3/main/streams/streams.c 2011-05-01 03:57:01 UTC (rev 310681) @@ -112,9 +112,32 @@ if (zend_hash_find(&EG(persistent_list), (char*)persistent_id, strlen(persistent_id)+1, (void*)&le) == SUCCESS) { if (Z_TYPE_P(le) == le_pstream) { if (stream) { + HashPosition pos; + zend_rsrc_list_entry *regentry; + ulong index = -1; /* intentional */ + + /* see if this persistent resource already has been loaded to the + * regular list; allowing the same resource in several entries in the + * regular list causes trouble (see bug #54623) */ + zend_hash_internal_pointer_reset_ex(&EG(regular_list),&pos); + while (zend_hash_get_current_data_ex(&EG(regular_list), + (void **)®entry,&pos) == SUCCESS) { + if (regentry->ptr == le->ptr) { + zend_hash_get_current_key_ex(&EG(regular_list), NULL, NULL, + &index, 0,&pos); + break; + } + zend_hash_move_forward_ex(&EG(regular_list),&pos); + } + *stream = (php_stream*)le->ptr; - le->refcount++; - (*stream)->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, *stream, le_pstream); + if (index == -1) { /* not found in regular list */ + le->refcount++; + (*stream)->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, *stream, le_pstream); + } else { + regentry->refcount++; + (*stream)->rsrc_id = index; + } } return PHP_STREAM_PERSISTENT_SUCCESS; } @@ -404,7 +427,7 @@ stream->orig_path = NULL; } -# if defined(PHP_WIN32) +# if defined(PHP_WIN32_) OutputDebugString(leakinfo); # else fprintf(stderr, "%s", leakinfo); Added: php/php-src/trunk/ext/standard/tests/streams/bug54623.phpt =================================================================== --- php/php-src/trunk/ext/standard/tests/streams/bug54623.phpt (rev 0) +++ php/php-src/trunk/ext/standard/tests/streams/bug54623.phpt 2011-05-01 03:57:01 UTC (rev 310681) @@ -0,0 +1,17 @@ +--TEST-- +Bug #54623: Segfault when when writing to a persistent socket after closing a copy of the socket +--FILE-- +<?php +$sock = pfsockopen('udp://127.0.0.1', '63844'); +var_dump((int)$sock); +fwrite($sock, "1"); +$sock2 = pfsockopen('udp://127.0.0.1', '63844'); +var_dump((int)$sock2); +fwrite($sock2, "2"); +fclose($sock2); +fwrite($sock, "3"); +--EXPECTF-- +int(%d) +int(%d) + +Warning: fwrite(): %d is not a valid stream resource in %s on line %d Modified: php/php-src/trunk/main/streams/streams.c =================================================================== --- php/php-src/trunk/main/streams/streams.c 2011-05-01 01:14:38 UTC (rev 310680) +++ php/php-src/trunk/main/streams/streams.c 2011-05-01 03:57:01 UTC (rev 310681) @@ -121,9 +121,32 @@ if (zend_hash_find(&EG(persistent_list), (char*)persistent_id, strlen(persistent_id)+1, (void*)&le) == SUCCESS) { if (Z_TYPE_P(le) == le_pstream) { if (stream) { + HashPosition pos; + zend_rsrc_list_entry *regentry; + ulong index = -1; /* intentional */ + + /* see if this persistent resource already has been loaded to the + * regular list; allowing the same resource in several entries in the + * regular list causes trouble (see bug #54623) */ + zend_hash_internal_pointer_reset_ex(&EG(regular_list),&pos); + while (zend_hash_get_current_data_ex(&EG(regular_list), + (void **)®entry,&pos) == SUCCESS) { + if (regentry->ptr == le->ptr) { + zend_hash_get_current_key_ex(&EG(regular_list), NULL, NULL, + &index, 0,&pos); + break; + } + zend_hash_move_forward_ex(&EG(regular_list),&pos); + } + *stream = (php_stream*)le->ptr; - le->refcount++; - (*stream)->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, *stream, le_pstream); + if (index == -1) { /* not found in regular list */ + le->refcount++; + (*stream)->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, *stream, le_pstream); + } else { + regentry->refcount++; + (*stream)->rsrc_id = index; + } } return PHP_STREAM_PERSISTENT_SUCCESS; } @@ -480,7 +503,7 @@ stream->orig_path = NULL; } -# if defined(PHP_WIN32) +# if defined(PHP_WIN32_) OutputDebugString(leakinfo); # else fprintf(stderr, "%s", leakinfo);
-- Wbr, Antony Dovgal --- http://pinba.org - realtime statistics for PHP -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php