Skip to content

Commit 93f65cd

Browse files
committed
- Fixed bug #54623 (Segfault when when writing to a persistent socket after
closing a copy of the socket).
1 parent 9c285fd commit 93f65cd

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Bug #54623: Segfault when when writing to a persistent socket after closing a copy of the socket
3+
--FILE--
4+
<?php
5+
$sock = pfsockopen('udp://127.0.0.1', '63844');
6+
var_dump((int)$sock);
7+
fwrite($sock, "1");
8+
$sock2 = pfsockopen('udp://127.0.0.1', '63844');
9+
var_dump((int)$sock2);
10+
fwrite($sock2, "2");
11+
fclose($sock2);
12+
fwrite($sock, "3");
13+
--EXPECTF--
14+
int(%d)
15+
int(%d)
16+
17+
Warning: fwrite(): %d is not a valid stream resource in %s on line %d

main/streams/streams.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,32 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
121121
if (zend_hash_find(&EG(persistent_list), (char*)persistent_id, strlen(persistent_id)+1, (void*) &le) == SUCCESS) {
122122
if (Z_TYPE_P(le) == le_pstream) {
123123
if (stream) {
124+
HashPosition pos;
125+
zend_rsrc_list_entry *regentry;
126+
ulong index = -1; /* intentional */
127+
128+
/* see if this persistent resource already has been loaded to the
129+
* regular list; allowing the same resource in several entries in the
130+
* regular list causes trouble (see bug #54623) */
131+
zend_hash_internal_pointer_reset_ex(&EG(regular_list), &pos);
132+
while (zend_hash_get_current_data_ex(&EG(regular_list),
133+
(void **)&regentry, &pos) == SUCCESS) {
134+
if (regentry->ptr == le->ptr) {
135+
zend_hash_get_current_key_ex(&EG(regular_list), NULL, NULL,
136+
&index, 0, &pos);
137+
break;
138+
}
139+
zend_hash_move_forward_ex(&EG(regular_list), &pos);
140+
}
141+
124142
*stream = (php_stream*)le->ptr;
125-
le->refcount++;
126-
(*stream)->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, *stream, le_pstream);
143+
if (index == -1) { /* not found in regular list */
144+
le->refcount++;
145+
(*stream)->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, *stream, le_pstream);
146+
} else {
147+
regentry->refcount++;
148+
(*stream)->rsrc_id = index;
149+
}
127150
}
128151
return PHP_STREAM_PERSISTENT_SUCCESS;
129152
}
@@ -480,7 +503,7 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
480503
stream->orig_path = NULL;
481504
}
482505

483-
# if defined(PHP_WIN32)
506+
# if defined(PHP_WIN32_)
484507
OutputDebugString(leakinfo);
485508
# else
486509
fprintf(stderr, "%s", leakinfo);

0 commit comments

Comments
 (0)