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);

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to