mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Fixed bug #72625 realpath() fails on non canonical long path
This commit is contained in:
parent
fc30b8e0f7
commit
0f16c56262
4 changed files with 148 additions and 7 deletions
53
ext/standard/tests/dir/bug72625.phpt
Normal file
53
ext/standard/tests/dir/bug72625.phpt
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72625 realpath() fails on very long argument.
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
if (substr(PHP_OS, 0, 3) != 'WIN') {
|
||||||
|
die("skip Valid only on Windows");
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$base = sys_get_temp_dir() . "/" . md5(uniqid());
|
||||||
|
while (strlen($base) < 260) {
|
||||||
|
$base = "$base/" . md5(uniqid());
|
||||||
|
}
|
||||||
|
|
||||||
|
$f0 = "$base/_test/documents/projects/myproject/vendor/name/library/classpath";
|
||||||
|
$f1 = "$f0/../../../../../../../../_test/documents/projects/myproject/vendor/name/library/../../../../../../../_test/documents/projects/myproject/vendor/name/library/classpath";
|
||||||
|
|
||||||
|
|
||||||
|
mkdir($f0, 0777, true);
|
||||||
|
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$f0,
|
||||||
|
file_exists($f0),
|
||||||
|
realpath($f0),
|
||||||
|
dirname($f0),
|
||||||
|
|
||||||
|
$f1,
|
||||||
|
file_exists($f1),
|
||||||
|
realpath($f1),
|
||||||
|
dirname($f1)
|
||||||
|
);
|
||||||
|
|
||||||
|
$tmp = $f0;
|
||||||
|
while ($tmp > $base) {
|
||||||
|
rmdir($tmp);
|
||||||
|
$tmp = dirname($tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
===DONE===
|
||||||
|
--EXPECTF--
|
||||||
|
string(%d) "%s/_test/documents/projects/myproject/vendor/name/library/classpath"
|
||||||
|
bool(true)
|
||||||
|
string(%d) "%s\_test\documents\projects\myproject\vendor\name\library\classpath"
|
||||||
|
string(%d) "%s\_test\documents\projects\myproject\vendor\name\library"
|
||||||
|
string(%d) "%s/_test/documents/projects/myproject/vendor/name/library/classpath/../../../../../../../../_test/documents/projects/myproject/vendor/name/library/../../../../../../../_test/documents/projects/myproject/vendor/name/library/classpath"
|
||||||
|
bool(true)
|
||||||
|
string(%d) "%s\_test\documents\projects\myproject\vendor\name\library\classpath"
|
||||||
|
string(%d) "%s\_test\documents\projects\myproject\vendor\name\library"
|
||||||
|
===DONE===
|
|
@ -19,6 +19,7 @@
|
||||||
#include <config.w32.h>
|
#include <config.w32.h>
|
||||||
|
|
||||||
#include <win32/time.h>
|
#include <win32/time.h>
|
||||||
|
#include <win32/ioutil.h>
|
||||||
#include <php.h>
|
#include <php.h>
|
||||||
|
|
||||||
#ifdef HAVE_LIBXML
|
#ifdef HAVE_LIBXML
|
||||||
|
@ -44,6 +45,12 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID dummy)
|
||||||
fprintf(stderr, "gettimeofday() initialization failed");
|
fprintf(stderr, "gettimeofday() initialization failed");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ret && php_win32_ioutil_init();
|
||||||
|
if (!ret) {
|
||||||
|
fprintf(stderr, "ioutil initialization failed");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#if 0 /* prepared */
|
#if 0 /* prepared */
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
|
|
@ -58,12 +58,18 @@
|
||||||
#include "win32/ioutil.h"
|
#include "win32/ioutil.h"
|
||||||
#include "win32/codepage.h"
|
#include "win32/codepage.h"
|
||||||
|
|
||||||
|
#include <pathcch.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#undef NONLS
|
#undef NONLS
|
||||||
#undef _WINNLS_
|
#undef _WINNLS_
|
||||||
#include <winnls.h>
|
#include <winnls.h>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef HRESULT (WINAPI *MyPathCchCanonicalizeEx)(_Out_ PWSTR pszPathOut, _In_ size_t cchPathOut, _In_ PCWSTR pszPathIn, _In_ unsigned long dwFlags);
|
||||||
|
|
||||||
|
static MyPathCchCanonicalizeEx canonicalize_path_w = NULL;
|
||||||
|
|
||||||
PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_ioutil_open_opts *opts)
|
PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_ioutil_open_opts *opts)
|
||||||
{/*{{{*/
|
{/*{{{*/
|
||||||
int current_umask;
|
int current_umask;
|
||||||
|
@ -500,6 +506,62 @@ PW32IO size_t php_win32_ioutil_dirname(char *path, size_t len)
|
||||||
return ret_len;
|
return ret_len;
|
||||||
}/*}}}*/
|
}/*}}}*/
|
||||||
|
|
||||||
|
PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len)
|
||||||
|
{/*{{{*/
|
||||||
|
wchar_t *pos, *idx = *buf, canonicalw[MAXPATHLEN];
|
||||||
|
size_t ret_len = len, canonicalw_len, shift;
|
||||||
|
|
||||||
|
if (len >= MAXPATHLEN) {
|
||||||
|
SET_ERRNO_FROM_WIN32_CODE(ERROR_BUFFER_OVERFLOW);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (NULL != (pos = wcschr(idx, PHP_WIN32_IOUTIL_FW_SLASHW)) && idx - *buf <= len) {
|
||||||
|
*pos = PHP_WIN32_IOUTIL_DEFAULT_SLASHW;
|
||||||
|
idx = pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
shift = PHP_WIN32_IOUTIL_IS_LONG_PATHW(*buf, len) ? PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW : 0;
|
||||||
|
if (S_OK != canonicalize_path_w(canonicalw, MAXPATHLEN, *buf + shift, PATHCCH_ALLOW_LONG_PATHS)) {
|
||||||
|
*new_len = ret_len;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
canonicalw_len = wcslen(canonicalw);
|
||||||
|
if (canonicalw_len + shift != len) {
|
||||||
|
if (canonicalw_len > len) {
|
||||||
|
*buf = realloc(*buf, (canonicalw_len + 1) * sizeof(wchar_t));
|
||||||
|
}
|
||||||
|
memmove(*buf + shift, canonicalw, (canonicalw_len + 1) * sizeof(wchar_t));
|
||||||
|
ret_len = canonicalw_len + shift;
|
||||||
|
}
|
||||||
|
*new_len = ret_len;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}/*}}}*/
|
||||||
|
|
||||||
|
static HRESULT MyPathCchCanonicalizeExFallback(_Out_ PWSTR pszPathOut, _In_ size_t cchPathOut, _In_ PCWSTR pszPathIn, _In_ unsigned long dwFlags)
|
||||||
|
{
|
||||||
|
pszPathOut = pszPathIn;
|
||||||
|
cchPathOut = wcslen(pszPathOut);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL php_win32_ioutil_init(void)
|
||||||
|
{
|
||||||
|
HMODULE hMod = GetModuleHandle("api-ms-win-core-path-l1-1-0");
|
||||||
|
|
||||||
|
if (hMod) {
|
||||||
|
canonicalize_path_w = (MyPathCchCanonicalizeEx)GetProcAddress(hMod, "PathCchCanonicalizeEx");
|
||||||
|
if (!canonicalize_path_w) {
|
||||||
|
canonicalize_path_w = MyPathCchCanonicalizeExFallback;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
canonicalize_path_w = MyPathCchCanonicalizeExFallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
/* an extended version could be implemented, for now direct functions can be used. */
|
/* an extended version could be implemented, for now direct functions can be used. */
|
||||||
#if 0
|
#if 0
|
||||||
PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode)
|
PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode)
|
||||||
|
|
|
@ -88,11 +88,15 @@ typedef enum {
|
||||||
} php_win32_ioutil_encoding;
|
} php_win32_ioutil_encoding;
|
||||||
|
|
||||||
|
|
||||||
#define PHP_WIN32_IOUTIL_DEFAULT_SLASHW L'\\'
|
#define PHP_WIN32_IOUTIL_FW_SLASHW L'/'
|
||||||
#define PHP_WIN32_IOUTIL_DEFAULT_SLASH '\\'
|
#define PHP_WIN32_IOUTIL_FW_SLASH '/'
|
||||||
|
#define PHP_WIN32_IOUTIL_BW_SLASHW L'\\'
|
||||||
|
#define PHP_WIN32_IOUTIL_BW_SLASH '\\'
|
||||||
|
#define PHP_WIN32_IOUTIL_DEFAULT_SLASHW PHP_WIN32_IOUTIL_BW_SLASHW
|
||||||
|
#define PHP_WIN32_IOUTIL_DEFAULT_SLASH PHP_WIN32_IOUTIL_BW_SLASH
|
||||||
|
|
||||||
#define PHP_WIN32_IOUTIL_DEFAULT_DIR_SEPARATORW L';'
|
#define PHP_WIN32_IOUTIL_DEFAULT_DIR_SEPARATORW L';'
|
||||||
#define PHP_WIN32_IOUTIL_IS_SLASHW(c) ((c) == L'\\' || (c) == L'/')
|
#define PHP_WIN32_IOUTIL_IS_SLASHW(c) ((c) == PHP_WIN32_IOUTIL_BW_SLASHW || (c) == PHP_WIN32_IOUTIL_FW_SLASHW)
|
||||||
#define PHP_WIN32_IOUTIL_IS_LETTERW(c) (((c) >= L'a' && (c) <= L'z') || ((c) >= L'A' && (c) <= L'Z'))
|
#define PHP_WIN32_IOUTIL_IS_LETTERW(c) (((c) >= L'a' && (c) <= L'z') || ((c) >= L'A' && (c) <= L'Z'))
|
||||||
#define PHP_WIN32_IOUTIL_JUNCTION_PREFIXW L"\\??\\"
|
#define PHP_WIN32_IOUTIL_JUNCTION_PREFIXW L"\\??\\"
|
||||||
#define PHP_WIN32_IOUTIL_JUNCTION_PREFIX_LENW 4
|
#define PHP_WIN32_IOUTIL_JUNCTION_PREFIX_LENW 4
|
||||||
|
@ -129,6 +133,13 @@ typedef enum {
|
||||||
} \
|
} \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len);
|
||||||
|
#ifdef PHP_EXPORTS
|
||||||
|
/* This symbols are needed only for the DllMain, but should not be exported
|
||||||
|
or be available when used with PHP binaries. */
|
||||||
|
BOOL php_win32_ioutil_init(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Keep these functions aliased for case some additional handling
|
/* Keep these functions aliased for case some additional handling
|
||||||
is needed later. */
|
is needed later. */
|
||||||
__forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, size_t in_len, size_t *out_len)
|
__forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, size_t in_len, size_t *out_len)
|
||||||
|
@ -148,11 +159,19 @@ __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, siz
|
||||||
free(mb);
|
free(mb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memmove(ret, PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW * sizeof(wchar_t));
|
|
||||||
memmove(ret+PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW, mb, mb_len * sizeof(wchar_t));
|
|
||||||
ret[mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW] = L'\0';
|
|
||||||
|
|
||||||
mb_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
|
(void)php_win32_ioutil_normalize_path_w(&mb, mb_len, &mb_len);
|
||||||
|
|
||||||
|
if (PHP_WIN32_IOUTIL_IS_LONG_PATHW(mb, mb_len)) {
|
||||||
|
memmove(ret, mb, mb_len * sizeof(wchar_t));
|
||||||
|
ret[mb_len] = L'\0';
|
||||||
|
} else {
|
||||||
|
memmove(ret, PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW * sizeof(wchar_t));
|
||||||
|
memmove(ret+PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW, mb, mb_len * sizeof(wchar_t));
|
||||||
|
ret[mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW] = L'\0';
|
||||||
|
|
||||||
|
mb_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
|
||||||
|
}
|
||||||
|
|
||||||
free(mb);
|
free(mb);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue