summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Scott <alex@cgi-central.net>2019-06-11 18:31:07 +0400
committerNikita Popov <nikita.ppv@gmail.com>2019-07-02 12:25:50 +0200
commita4acff3e21778e8d1f635cf74611b1c13de5ee2a (patch)
tree9d7faba1218604cd118d0ca18a5f375146e36049
parent57688ad7bff7e769078d1e670a65853635d31a71 (diff)
downloadphp-git-a4acff3e21778e8d1f635cf74611b1c13de5ee2a.tar.gz
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)
-rw-r--r--ext/opcache/ZendAccelerator.c25
1 files changed, 24 insertions, 1 deletions
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)<sizeof("phar://.phar")) ||
+ memcmp(ZSTR_VAL(persistent_script->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();