From: Alex Scott Date: Tue, 11 Jun 2019 14:31:07 +0000 (+0400) Subject: Fix bug #78138: opcache.validate_permission incorrectly works with PHAR files X-Git-Tag: php-7.2.21RC1~18 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a4acff3e21778e8d1f635cf74611b1c13de5ee2a;p=php Fix bug #78138: opcache.validate_permission incorrectly works with PHAR files opcache incorrectly handles PHAR files when opcache.validate_permission option enabled, because it calls access("phar://path-to/file.phar/path/inside.php", R_OK); rather than access("path-to/file.phar", R_OK) --- diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index b6c001d637..1562922424 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -1760,6 +1760,29 @@ zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type) } #endif +int check_persistent_script_access(zend_persistent_script *persistent_script) +{ + char *phar_path, *ptr; + int ret; + if ((ZSTR_LEN(persistent_script->script.filename)script.filename), "phar://", sizeof("phar://")-1)) { + + return access(ZSTR_VAL(persistent_script->script.filename), R_OK) != 0; + + } else { + /* we got a cached file from .phar, so we have to strip prefix and path inside .phar to check access() */ + phar_path = estrdup(ZSTR_VAL(persistent_script->script.filename)+sizeof("phar://")-1); + if ((ptr = strstr(phar_path, ".phar/")) != NULL) + { + *(ptr+sizeof(".phar/")-2) = 0; /* strip path inside .phar file */ + } + ret = access(phar_path, R_OK) != 0; + efree(phar_path); + return ret; + } +} + + /* zend_compile() replacement */ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) { @@ -1896,7 +1919,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) if (EXPECTED(persistent_script != NULL) && UNEXPECTED(ZCG(accel_directives).validate_permission) && file_handle->type == ZEND_HANDLE_FILENAME && - UNEXPECTED(access(ZSTR_VAL(persistent_script->script.filename), R_OK) != 0)) { + UNEXPECTED(check_persistent_script_access(persistent_script))) { if (type == ZEND_REQUIRE) { zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename); zend_bailout();