mirror of
https://github.com/php/php-src.git
synced 2024-11-23 09:54:15 +08:00
- Fix #48746, improve fix to support all possible cases (see latest comment in the report)
This commit is contained in:
parent
62d78d7ccc
commit
ada5eb95ad
@ -667,11 +667,14 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
|
||||
/* File is a reparse point. Get the target */
|
||||
HANDLE hLink = NULL;
|
||||
REPARSE_DATA_BUFFER * pbuffer;
|
||||
unsigned int retlength = 0, rname_off = 0;
|
||||
int bufindex = 0, rname_len = 0, isabsolute = 0;
|
||||
unsigned int retlength = 0;
|
||||
int bufindex = 0, isabsolute = 0;
|
||||
wchar_t * reparsetarget;
|
||||
WCHAR szVolumePathNames[MAX_PATH];
|
||||
BOOL isVolume = FALSE;
|
||||
char printname[MAX_PATH];
|
||||
char substitutename[MAX_PATH];
|
||||
int printname_len, substitutename_len;
|
||||
int substitutename_off = 0;
|
||||
|
||||
if(++(*ll) > LINK_MAX) {
|
||||
return -1;
|
||||
@ -692,33 +695,61 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
|
||||
CloseHandle(hLink);
|
||||
|
||||
if(pbuffer->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
|
||||
rname_len = pbuffer->SymbolicLinkReparseBuffer.PrintNameLength/2;
|
||||
rname_off = pbuffer->SymbolicLinkReparseBuffer.PrintNameOffset/2;
|
||||
if(rname_len <= 0) {
|
||||
rname_len = pbuffer->SymbolicLinkReparseBuffer.SubstituteNameLength/2;
|
||||
rname_off = pbuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset/2;
|
||||
}
|
||||
|
||||
reparsetarget = pbuffer->SymbolicLinkReparseBuffer.ReparseTarget;
|
||||
printname_len = pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
|
||||
isabsolute = (pbuffer->SymbolicLinkReparseBuffer.Flags == 0) ? 1 : 0;
|
||||
if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
|
||||
reparsetarget + pbuffer->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR),
|
||||
printname_len + 1,
|
||||
printname, MAX_PATH, NULL, NULL
|
||||
)) {
|
||||
tsrm_free_alloca(pbuffer, use_heap_large);
|
||||
return -1;
|
||||
};
|
||||
printname_len = pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
|
||||
printname[printname_len] = 0;
|
||||
|
||||
substitutename_len = pbuffer->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
|
||||
if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
|
||||
reparsetarget + pbuffer->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
||||
substitutename_len + 1,
|
||||
substitutename, MAX_PATH, NULL, NULL
|
||||
)) {
|
||||
tsrm_free_alloca(pbuffer, use_heap_large);
|
||||
return -1;
|
||||
};
|
||||
substitutename[substitutename_len] = 0;
|
||||
}
|
||||
else if(pbuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
|
||||
rname_len = pbuffer->MountPointReparseBuffer.PrintNameLength/2;
|
||||
rname_off = pbuffer->MountPointReparseBuffer.PrintNameOffset/2;
|
||||
if(rname_len <= 0) {
|
||||
rname_len = pbuffer->MountPointReparseBuffer.SubstituteNameLength/2;
|
||||
rname_off = pbuffer->MountPointReparseBuffer.SubstituteNameOffset/2;
|
||||
}
|
||||
|
||||
reparsetarget = pbuffer->MountPointReparseBuffer.ReparseTarget;
|
||||
isabsolute = 1;
|
||||
}
|
||||
else {
|
||||
reparsetarget = pbuffer->MountPointReparseBuffer.ReparseTarget;
|
||||
printname_len = pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR);
|
||||
if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
|
||||
reparsetarget + pbuffer->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR),
|
||||
printname_len + 1,
|
||||
printname, MAX_PATH, NULL, NULL
|
||||
)) {
|
||||
tsrm_free_alloca(pbuffer, use_heap_large);
|
||||
return -1;
|
||||
};
|
||||
printname[pbuffer->MountPointReparseBuffer.PrintNameLength / sizeof(WCHAR)] = 0;
|
||||
|
||||
substitutename_len = pbuffer->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
|
||||
if (!WideCharToMultiByte(CP_THREAD_ACP, 0,
|
||||
reparsetarget + pbuffer->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
||||
substitutename_len + 1,
|
||||
substitutename, MAX_PATH, NULL, NULL
|
||||
)) {
|
||||
tsrm_free_alloca(pbuffer, use_heap_large);
|
||||
return -1;
|
||||
};
|
||||
substitutename[substitutename_len] = 0;
|
||||
} else {
|
||||
tsrm_free_alloca(pbuffer, use_heap_large);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(isabsolute && rname_len > 4) {
|
||||
if(isabsolute && substitutename_len > 4) {
|
||||
/* Do not resolve volumes (for now). A mounted point can
|
||||
target a volume without a drive, it is not certain that
|
||||
all IO functions we use in php and its deps support
|
||||
@ -726,21 +757,22 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
|
||||
d:\test\mnt\foo
|
||||
\\?\Volume{62d1c3f8-83b9-11de-b108-806e6f6e6963}\foo
|
||||
*/
|
||||
if (wcsncmp(reparsetarget, L"\\??\\Volume{",11) == 0
|
||||
|| wcsncmp(reparsetarget, L"\\\\?\\Volume{",11) == 0) {
|
||||
if (strncmp(substitutename, "\\??\\Volume{",11) == 0
|
||||
|| strncmp(substitutename, "\\\\?\\Volume{",11) == 0) {
|
||||
isVolume = TRUE;
|
||||
substitutename_off = 0;
|
||||
} else
|
||||
/* do not use the \??\ and \\?\ prefix*/
|
||||
if (wcsncmp(reparsetarget, L"\\??\\", 4) == 0
|
||||
|| wcsncmp(reparsetarget, L"\\\\?\\", 4) == 0) {
|
||||
rname_off += 4;
|
||||
rname_len -= 4;
|
||||
if (strncmp(substitutename, "\\??\\", 4) == 0
|
||||
|| strncmp(substitutename, "\\\\?\\", 4) == 0) {
|
||||
substitutename_off = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isVolume) {
|
||||
/* Convert wide string to narrow string */
|
||||
for(bufindex = 0; bufindex < rname_len; bufindex++) {
|
||||
*(path + bufindex) = (char)(reparsetarget[rname_off + bufindex]);
|
||||
char * tmp = substitutename + substitutename_off;
|
||||
for(bufindex = 0; bufindex < (substitutename_len - substitutename_off); bufindex++) {
|
||||
*(path + bufindex) = *(tmp + bufindex);
|
||||
}
|
||||
|
||||
*(path + bufindex) = 0;
|
||||
@ -748,6 +780,13 @@ static int tsrm_realpath_r(char *path, int start, int len, int *ll, time_t *t, i
|
||||
} else {
|
||||
j = len;
|
||||
}
|
||||
|
||||
|
||||
#if VIRTUAL_CWD_DEBUG
|
||||
fprintf(stderr, "reparse: print: %s ", printname);
|
||||
fprintf(stderr, "sub: %s ", substitutename);
|
||||
fprintf(stderr, "resolved: %s ", path);
|
||||
#endif
|
||||
tsrm_free_alloca(pbuffer, use_heap_large);
|
||||
|
||||
if(isabsolute == 1) {
|
||||
|
Loading…
Reference in New Issue
Block a user