diff --git a/ext/phar/tests/gh14481.phpt b/ext/phar/tests/gh14481.phpt new file mode 100644 index 000000000000..c87d6538bddc --- /dev/null +++ b/ext/phar/tests/gh14481.phpt @@ -0,0 +1,61 @@ +--TEST-- +GH-14481 (realpath() and SplFileInfo::getRealPath inside Phar) +--EXTENSIONS-- +phar +--INI-- +phar.readonly=0 +--FILE-- +addFromString('inner.php', "setStub("getRealPath()); + +echo "SplFileInfo missing entry:\n"; +var_dump((new SplFileInfo($missing))->getRealPath()); + +echo "PharFileInfo existing entry:\n"; +var_dump((new PharFileInfo($existing))->getRealPath()); + +echo "RecursiveIteratorIterator entry:\n"; +foreach (new RecursiveIteratorIterator(new Phar($file)) as $info) { + var_dump($info->getRealPath()); +} + +echo "plain-filesystem branch unaffected:\n"; +var_dump(realpath(__FILE__) === __FILE__); +?> +--CLEAN-- + +--EXPECTF-- +realpath existing entry: +string(%d) "phar://%sgh14481.phar/inner.php" +realpath missing entry: +bool(false) +SplFileInfo existing entry: +string(%d) "phar://%sgh14481.phar/inner.php" +SplFileInfo missing entry: +bool(false) +PharFileInfo existing entry: +string(%d) "phar://%sgh14481.phar/inner.php" +RecursiveIteratorIterator entry: +string(%d) "phar://%sgh14481.phar/inner.php" +plain-filesystem branch unaffected: +bool(true) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 89af25dd9d35..c9477ab47c20 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1244,6 +1244,17 @@ PHP_METHOD(SplFileInfo, getRealPath) filename = intern->file_name ? ZSTR_VAL(intern->file_name) : NULL; } + if (filename) { + const char *path_to_open = filename; + php_stream_wrapper *wrapper = php_stream_locate_url_wrapper(filename, &path_to_open, 0); + if (wrapper && wrapper != &php_plain_files_wrapper && !wrapper->is_url && wrapper->wops && wrapper->wops->url_stat) { + php_stream_statbuf ssb; + if (wrapper->wops->url_stat(wrapper, path_to_open, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) == 0) { + RETURN_STRING(filename); + } + RETURN_FALSE; + } + } if (filename && VCWD_REALPATH(filename, buff)) { #ifdef ZTS diff --git a/ext/standard/file.c b/ext/standard/file.c index 1841c242b870..2fe8a8c39a84 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -2102,6 +2102,16 @@ PHP_FUNCTION(realpath) Z_PARAM_PATH(filename, filename_len) ZEND_PARSE_PARAMETERS_END(); + const char *path_to_open = filename; + php_stream_wrapper *wrapper = php_stream_locate_url_wrapper(filename, &path_to_open, 0); + if (wrapper && wrapper != &php_plain_files_wrapper && !wrapper->is_url && wrapper->wops && wrapper->wops->url_stat) { + php_stream_statbuf ssb; + if (wrapper->wops->url_stat(wrapper, path_to_open, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) == 0) { + RETURN_STRINGL(filename, filename_len); + } + RETURN_FALSE; + } + if (VCWD_REALPATH(filename, resolved_path_buff)) { if (php_check_open_basedir(resolved_path_buff)) { RETURN_FALSE;