diff options
author | Gustavo André dos Santos Lopes <cataphract@php.net> | 2011-05-01 03:57:01 +0000 |
---|---|---|
committer | Gustavo André dos Santos Lopes <cataphract@php.net> | 2011-05-01 03:57:01 +0000 |
commit | 93f65cdeac1e20e5ad789609894c116261e7f273 (patch) | |
tree | c31c6a65dfbe3413164d4434fa9a28fa83da62d6 | |
parent | 9c285fddbb01de190098fc0b1964566f5a217327 (diff) | |
download | php-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.phpt | 17 | ||||
-rwxr-xr-x | main/streams/streams.c | 29 |
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 **)®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 @@ 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); |