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 **)&regentry,&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 **)&regentry,&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

Reply via email to