]> granicus.if.org Git - php/commitdiff
Fix #79806: realpath() erroneously resolves link to link
authorChristoph M. Becker <cmbecker69@gmx.de>
Wed, 15 Jul 2020 16:37:27 +0000 (18:37 +0200)
committerChristoph M. Becker <cmbecker69@gmx.de>
Mon, 27 Jul 2020 13:08:39 +0000 (15:08 +0200)
After resolving reparse points, the path still may be a reparse point;
in that case we have to resolve that reparse point as well.

NEWS
Zend/zend_virtual_cwd.c
ext/standard/tests/file/realpath_basic4.phpt

diff --git a/NEWS b/NEWS
index 0a6e60d4192ec7f18383b4e0170512c384d45fef..ffb7d830cb64ba4ce44fe43b142a559e20b2dd16 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ PHP                                                                        NEWS
 - Core:
   . Fixed bug #79884 (PHP_CONFIG_FILE_PATH is meaningless). (cmb)
   . Fixed bug #77932 (File extensions are case-sensitive). (cmb)
+  . Fixed bug #79806 (realpath() erroneously resolves link to link). (cmb)
 
 ?? ??? ????, PHP 7.3.21
 
index 253ed8c42026274ec74bdcf23e8a2a2e50d8d6c0..3b90074683b28c2888bd275ed21901da97306f28 100644 (file)
@@ -845,6 +845,7 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim
                }
 
 #ifdef ZEND_WIN32
+retry_reparse_point:
                if (save) {
                        pathw = php_win32_ioutil_any_to_w(path);
                        if (!pathw) {
@@ -867,7 +868,7 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim
                tmp = do_alloca(len+1, use_heap);
                memcpy(tmp, path, len+1);
 
-retry:
+retry_reparse_tag_cloud:
                if(save &&
                                !(IS_UNC_PATH(path, len) && len >= 3 && path[2] != '?') &&
                                (dataw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
@@ -928,7 +929,7 @@ retry:
                                        dataw.dwFileAttributes = fileInformation.dwFileAttributes;
                                        CloseHandle(hLink);
                                        (*ll)--;
-                                       goto retry;
+                                       goto retry_reparse_tag_cloud;
                                }
                                free_alloca(tmp, use_heap);
                                CloseHandle(hLink);
@@ -1075,6 +1076,15 @@ retry:
                        free_alloca(pbuffer, use_heap_large);
                        free(substitutename);
 
+                       {
+                               DWORD attrs = GetFileAttributesA(path);
+                               if (!isVolume && (attrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
+                                       free_alloca(tmp, use_heap);
+                                       FREE_PATHW()
+                                       goto retry_reparse_point;
+                               }
+                       }
+
                        if(isabsolute == 1) {
                                if (!((j == 3) && (path[1] == ':') && (path[2] == '\\'))) {
                                        /* use_realpath is 0 in the call below coz path is absolute*/
index d782b6d618fa9a0f022b55e6f132bc545747441f..5f18dd9841656ff33dce2b23ecf65bd8173a1f56 100644 (file)
@@ -1,11 +1,5 @@
 --TEST--
 Test realpath() with relative paths
---SKIPIF--
-<?php
-if (substr(PHP_OS, 0, 3) == 'WIN') {
-    die('skip no symlinks on Windows');
-}
-?>
 --FILE--
 <?php
 $file_path = dirname(__FILE__);