diff options
author | Sara Golemon <pollita@php.net> | 2004-06-21 18:58:55 +0000 |
---|---|---|
committer | Sara Golemon <pollita@php.net> | 2004-06-21 18:58:55 +0000 |
commit | 7fcfa8865e97a6c8141532187428d9dd9d1217e5 (patch) | |
tree | c5686f91dea2654cd3bad7d90bf36ae2f5decc5a /main/streams/streams.c | |
parent | d9226a1dd0e0644334adecbfa9ab4b76969610fa (diff) | |
download | php-git-7fcfa8865e97a6c8141532187428d9dd9d1217e5.tar.gz |
BugFix#28868: Wrapper hash not thread-safe.
Userdefined wrappers were being registered into a global wrapper hash
which can cross threads. Termination of once instance then has the
potential to leave an active stream in another instance with no wrapper
leading to segfault.
Diffstat (limited to 'main/streams/streams.c')
-rwxr-xr-x | main/streams/streams.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/main/streams/streams.c b/main/streams/streams.c index df5b506029..7b3439b428 100755 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -34,6 +34,7 @@ #include "php_streams_int.h" /* {{{ resource and registration code */ +/* Global wrapper hash, copied to FG(stream_wrappers) on registration of volatile wrapper */ static HashTable url_stream_wrappers_hash; static int le_stream = FAILURE; /* true global */ static int le_pstream = FAILURE; /* true global */ @@ -48,9 +49,9 @@ PHPAPI int php_file_le_pstream(void) return le_pstream; } -PHPAPI HashTable *php_stream_get_url_stream_wrappers_hash() +PHPAPI HashTable *_php_stream_get_url_stream_wrappers_hash(TSRMLS_D) { - return &url_stream_wrappers_hash; + return (FG(stream_wrappers) ? FG(stream_wrappers) : &url_stream_wrappers_hash); } static int _php_stream_release_context(list_entry *le, void *pContext TSRMLS_DC) @@ -1374,6 +1375,7 @@ int php_shutdown_stream_wrappers(int module_number TSRMLS_DC) return SUCCESS; } +/* API for registering GLOBAL wrappers */ PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC) { return zend_hash_add(&url_stream_wrappers_hash, protocol, strlen(protocol), wrapper, sizeof(*wrapper), NULL); @@ -1383,11 +1385,27 @@ PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC) { return zend_hash_del(&url_stream_wrappers_hash, protocol, strlen(protocol)); } + +/* API for registering VOLATILE wrappers */ +PHPAPI int php_register_url_stream_wrapper_volatile(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC) +{ + if (!FG(stream_wrappers)) { + php_stream_wrapper tmpwrapper; + + FG(stream_wrappers) = emalloc(sizeof(HashTable)); + zend_hash_init(FG(stream_wrappers), 0, NULL, NULL, 1); + zend_hash_copy(FG(stream_wrappers), &url_stream_wrappers_hash, NULL, &tmpwrapper, sizeof(php_stream_wrapper)); + } + + return zend_hash_add(FG(stream_wrappers), protocol, strlen(protocol), wrapper, sizeof(*wrapper), NULL); +} + /* }}} */ /* {{{ php_stream_locate_url_wrapper */ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, char **path_for_open, int options TSRMLS_DC) { + HashTable *wrapper_hash = (FG(stream_wrappers) ? FG(stream_wrappers) : &url_stream_wrappers_hash); php_stream_wrapper *wrapper = NULL; const char *p, *protocol = NULL; int n = 0; @@ -1414,7 +1432,7 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, char } if (protocol) { - if (FAILURE == zend_hash_find(&url_stream_wrappers_hash, (char*)protocol, n, (void**)&wrapper)) { + if (FAILURE == zend_hash_find(wrapper_hash, (char*)protocol, n, (void**)&wrapper)) { char wrapper_name[32]; if (n >= sizeof(wrapper_name)) |