Fix #80258: Windows Deduplication Enabled, randon permission errors

A recent bug fix regarding symlinks claimed:

> After resolving reparse points, the path still may be a reparse
> point; in that case we have to resolve that reparse point as well.

While that is basically correct, some reparse points may point to
inaccessible system folders (e.g. `IO_REPARSE_TAG_DEDUP` points to
"\System Volume Information").  Since we don't know details about
arbitrary reparse points, and are mainly interested in nested symlinks,
we take a step back, and only resolve `IO_REPARSE_TAG_SYMLINK` for now.

Close GH-6354.
This commit is contained in:
Christoph M. Becker 2020-10-19 17:41:58 +02:00
parent 2be27074b6
commit 848e24f24d
2 changed files with 6 additions and 2 deletions

2
NEWS
View file

@ -5,6 +5,8 @@ PHP NEWS
- Core: - Core:
. Fixed bug #80280 (ADD_EXTENSION_DEP() fails for ext/standard and ext/date). . Fixed bug #80280 (ADD_EXTENSION_DEP() fails for ext/standard and ext/date).
(cmb) (cmb)
. Fixed bug #80258 (Windows Deduplication Enabled, randon permission errors).
(cmb)
- IMAP: - IMAP:
. Fixed bug #64076 (imap_sort() does not return FALSE on failure). (cmb) . Fixed bug #64076 (imap_sort() does not return FALSE on failure). (cmb)

View file

@ -741,7 +741,7 @@ CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void)
static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, time_t *t, int use_realpath, int is_dir, int *link_is_dir) /* {{{ */ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, time_t *t, int use_realpath, int is_dir, int *link_is_dir) /* {{{ */
{ {
size_t i, j; size_t i, j;
int directory = 0, save; int directory = 0, save, may_retry_reparse_point;
#ifdef ZEND_WIN32 #ifdef ZEND_WIN32
WIN32_FIND_DATAW dataw; WIN32_FIND_DATAW dataw;
HANDLE hFind = INVALID_HANDLE_VALUE; HANDLE hFind = INVALID_HANDLE_VALUE;
@ -846,6 +846,7 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim
#ifdef ZEND_WIN32 #ifdef ZEND_WIN32
retry_reparse_point: retry_reparse_point:
may_retry_reparse_point = 0;
if (save) { if (save) {
pathw = php_win32_ioutil_any_to_w(path); pathw = php_win32_ioutil_any_to_w(path);
if (!pathw) { if (!pathw) {
@ -940,6 +941,7 @@ retry_reparse_tag_cloud:
CloseHandle(hLink); CloseHandle(hLink);
if(pbuffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) { if(pbuffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
may_retry_reparse_point = 1;
reparsetarget = pbuffer->SymbolicLinkReparseBuffer.ReparseTarget; reparsetarget = pbuffer->SymbolicLinkReparseBuffer.ReparseTarget;
isabsolute = (pbuffer->SymbolicLinkReparseBuffer.Flags == 0) ? 1 : 0; isabsolute = (pbuffer->SymbolicLinkReparseBuffer.Flags == 0) ? 1 : 0;
#if VIRTUAL_CWD_DEBUG #if VIRTUAL_CWD_DEBUG
@ -1076,7 +1078,7 @@ retry_reparse_tag_cloud:
free_alloca(pbuffer, use_heap_large); free_alloca(pbuffer, use_heap_large);
free(substitutename); free(substitutename);
{ if (may_retry_reparse_point) {
DWORD attrs; DWORD attrs;
FREE_PATHW() FREE_PATHW()