summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo André dos Santos Lopes <cataphract@php.net>2011-05-01 03:57:01 +0000
committerGustavo André dos Santos Lopes <cataphract@php.net>2011-05-01 03:57:01 +0000
commit93f65cdeac1e20e5ad789609894c116261e7f273 (patch)
treec31c6a65dfbe3413164d4434fa9a28fa83da62d6
parent9c285fddbb01de190098fc0b1964566f5a217327 (diff)
downloadphp-git-93f65cdeac1e20e5ad789609894c116261e7f273.tar.gz
- Fixed bug #54623 (Segfault when when writing to a persistent socket after
closing a copy of the socket).
-rw-r--r--ext/standard/tests/streams/bug54623.phpt17
-rwxr-xr-xmain/streams/streams.c29
2 files changed, 43 insertions, 3 deletions
diff --git a/ext/standard/tests/streams/bug54623.phpt b/ext/standard/tests/streams/bug54623.phpt
new file mode 100644
index 0000000000..cd83854f43
--- /dev/null
+++ b/ext/standard/tests/streams/bug54623.phpt
@@ -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
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 99cdf26f3d..caa7e1d0f9 100755
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -121,9 +121,32 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
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 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
stream->orig_path = NULL;
}
-# if defined(PHP_WIN32)
+# if defined(PHP_WIN32_)
OutputDebugString(leakinfo);
# else
fprintf(stderr, "%s", leakinfo);