From 53bbf1238cd3f19c3f869f1a01704cdbab60c712 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 10 Jul 2008 11:36:50 +0000 Subject: [PATCH] Extensions MUST NOT manipulate with internal functions from EG(function_table) in run-time. It may cause problems with opcode caches and in multi-threaded environment. Now the same functions are overriden at MINIT and call original functions or PHAR ones dependent on flag setting. --- ext/phar/func_interceptors.c | 77 ++++++++++++++++++++++++++++-------- ext/phar/func_interceptors.h | 2 + ext/phar/phar.c | 14 +++++-- ext/phar/phar_internal.h | 1 + 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index 81d3ec710b..08cdcc18b1 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -29,6 +29,10 @@ PHAR_FUNC(phar_opendir) /* {{{ */ int filename_len; zval *zcontext = NULL; + if (!PHAR_G(intercepted)) { + goto skip_phar; + } + if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) && !cached_phars.arBuckets) { goto skip_phar; @@ -98,6 +102,10 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */ long maxlen = PHP_STREAM_COPY_ALL; zval *zcontext = NULL; + if (!PHAR_G(intercepted)) { + goto skip_phar; + } + if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) && !cached_phars.arBuckets) { goto skip_phar; @@ -224,6 +232,10 @@ PHAR_FUNC(phar_readfile) /* {{{ */ zval *zcontext = NULL; php_stream *stream; + if (!PHAR_G(intercepted)) { + goto skip_phar; + } + if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) && !cached_phars.arBuckets) { goto skip_phar; @@ -315,6 +327,10 @@ PHAR_FUNC(phar_fopen) /* {{{ */ zval *zcontext = NULL; php_stream *stream; + if (!PHAR_G(intercepted)) { + goto skip_phar; + } + if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) && !cached_phars.arBuckets) { /* no need to check, include_path not even specified in fopen/ no active phars */ @@ -792,14 +808,18 @@ skip_phar: #define PharFileFunction(fname, funcnum, orig) \ void fname(INTERNAL_FUNCTION_PARAMETERS) { \ - char *filename; \ - int filename_len; \ - \ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \ - return; \ + if (!PHAR_G(intercepted)) { \ + PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \ + } else { \ + char *filename; \ + int filename_len; \ + \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \ + return; \ + } \ + \ + phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \ } \ - \ - phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \ } /* }}} */ @@ -878,6 +898,10 @@ PHAR_FUNC(phar_is_file) /* {{{ */ char *filename; int filename_len; + if (!PHAR_G(intercepted)) { + goto skip_phar; + } + if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) && !cached_phars.arBuckets) { goto skip_phar; @@ -939,6 +963,10 @@ PHAR_FUNC(phar_is_link) /* {{{ */ char *filename; int filename_len; + if (!PHAR_G(intercepted)) { + goto skip_phar; + } + if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map))) && !cached_phars.arBuckets) { goto skip_phar; @@ -1006,6 +1034,26 @@ PharFileFunction(phar_stat, FS_STAT, orig_stat) /* }}} */ /* {{{ void phar_intercept_functions(TSRMLS_D) */ +void phar_intercept_functions(TSRMLS_D) +{ + zend_function *orig; + + if (!PHAR_G(request_init)) { + PHAR_G(cwd) = NULL; + PHAR_G(cwd_len) = 0; + } + PHAR_G(intercepted) = 1; +} +/* }}} */ + +/* {{{ void phar_release_functions(TSRMLS_D) */ +void phar_release_functions(TSRMLS_D) +{ + PHAR_G(intercepted) = 0; +} +/* }}} */ + +/* {{{ void phar_intercept_functions_init(TSRMLS_D) */ #define PHAR_INTERCEPT(func) \ PHAR_G(orig_##func) = NULL; \ if (SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \ @@ -1013,17 +1061,10 @@ PharFileFunction(phar_stat, FS_STAT, orig_stat) orig->internal_function.handler = phar_##func; \ } -void phar_intercept_functions(TSRMLS_D) +void phar_intercept_functions_init(TSRMLS_D) { zend_function *orig; - if (!PHAR_G(request_init)) { - PHAR_G(cwd) = NULL; - PHAR_G(cwd_len) = 0; - } else if (PHAR_G(orig_fopen)) { - /* don't double-intercept */ - return; - } PHAR_INTERCEPT(fopen); PHAR_INTERCEPT(file_get_contents); PHAR_INTERCEPT(is_file); @@ -1046,17 +1087,18 @@ void phar_intercept_functions(TSRMLS_D) PHAR_INTERCEPT(lstat); PHAR_INTERCEPT(stat); PHAR_INTERCEPT(readfile); + PHAR_G(intercepted) = 0; } /* }}} */ -/* {{{ void phar_release_functions(TSRMLS_D) */ +/* {{{ void phar_intercept_functions_shutdown(TSRMLS_D) */ #define PHAR_RELEASE(func) \ if (PHAR_G(orig_##func) && SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \ orig->internal_function.handler = PHAR_G(orig_##func); \ } \ PHAR_G(orig_##func) = NULL; -void phar_release_functions(TSRMLS_D) +void phar_intercept_functions_shutdown(TSRMLS_D) { zend_function *orig; @@ -1081,6 +1123,7 @@ void phar_release_functions(TSRMLS_D) PHAR_RELEASE(lstat); PHAR_RELEASE(stat); PHAR_RELEASE(readfile); + PHAR_G(intercepted) = 0; } /* }}} */ diff --git a/ext/phar/func_interceptors.h b/ext/phar/func_interceptors.h index b48be591ed..e161df6d34 100644 --- a/ext/phar/func_interceptors.h +++ b/ext/phar/func_interceptors.h @@ -22,6 +22,8 @@ BEGIN_EXTERN_C() void phar_intercept_functions(TSRMLS_D); void phar_release_functions(TSRMLS_D); +void phar_intercept_functions_init(TSRMLS_D); +void phar_intercept_functions_shutdown(TSRMLS_D); END_EXTERN_C() /* diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 0a6a7f86d1..d8c9bb78d9 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -3299,13 +3299,18 @@ PHP_MINIT_FUNCTION(phar) /* {{{ */ phar_object_init(TSRMLS_C); + phar_intercept_functions_init(TSRMLS_C); + return php_register_url_stream_wrapper("phar", &php_stream_phar_wrapper TSRMLS_CC); } /* }}} */ PHP_MSHUTDOWN_FUNCTION(phar) /* {{{ */ { - return php_unregister_url_stream_wrapper("phar" TSRMLS_CC); + php_unregister_url_stream_wrapper("phar" TSRMLS_CC); + + phar_intercept_functions_shutdown(TSRMLS_C); + if (zend_compile_file == phar_compile_file) { zend_compile_file = phar_orig_compile_file; } @@ -3319,6 +3324,8 @@ PHP_MSHUTDOWN_FUNCTION(phar) /* {{{ */ zend_hash_destroy(&(cached_phars)); zend_hash_destroy(&(cached_alias)); } + + return SUCCESS; } /* }}} */ @@ -3353,9 +3360,7 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */ PHAR_G(cwd) = NULL; PHAR_G(cwd_len) = 0; PHAR_G(cwd_init) = 0; - if (!PHAR_G(orig_fopen)) { - phar_intercept_functions(TSRMLS_C); - } + phar_intercept_functions(TSRMLS_C); } } /* }}} */ @@ -3451,6 +3456,7 @@ static zend_module_dep phar_deps[] = { ZEND_MOD_OPTIONAL("bz2") ZEND_MOD_OPTIONAL("openssl") ZEND_MOD_OPTIONAL("zlib") + ZEND_MOD_OPTIONAL("standard") #if HAVE_SPL ZEND_MOD_REQUIRED("spl") #endif diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index e8873dec5c..e2e415eeab 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -158,6 +158,7 @@ ZEND_BEGIN_MODULE_GLOBALS(phar) int has_bz2; zend_bool readonly_orig; zend_bool require_hash_orig; + zend_bool intercepted; int request_init; int require_hash; int request_done; -- 2.40.0