mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-7.1'
* PHP-7.1: Fixed bug #73877 readlink() returns garbage for UTF-8 paths
This commit is contained in:
commit
628c5a31da
2 changed files with 72 additions and 30 deletions
|
@ -165,10 +165,9 @@ static inline time_t FileTimeToUnixTime(const FILETIME *FileTime)
|
|||
|
||||
CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){ /* {{{ */
|
||||
HANDLE hFile;
|
||||
DWORD dwRet;
|
||||
wchar_t *linkw = php_win32_ioutil_any_to_w(link), targetw[MAXPATHLEN];
|
||||
size_t _tmp_len;
|
||||
char *_tmp;
|
||||
size_t ret_len, targetw_len, offset = 0;
|
||||
char *ret;
|
||||
|
||||
if (!linkw) {
|
||||
return -1;
|
||||
|
@ -197,46 +196,39 @@ CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){
|
|||
with VS2012 and earlier, and seems not to be fixed till
|
||||
now. Thus, correcting target_len so it's suddenly don't
|
||||
overflown. */
|
||||
dwRet = GetFinalPathNameByHandleW(hFile, targetw, MAXPATHLEN, VOLUME_NAME_DOS);
|
||||
if(dwRet >= target_len || dwRet >= MAXPATHLEN || dwRet == 0) {
|
||||
targetw_len = GetFinalPathNameByHandleW(hFile, targetw, MAXPATHLEN, VOLUME_NAME_DOS);
|
||||
if(targetw_len >= target_len || targetw_len >= MAXPATHLEN || targetw_len == 0) {
|
||||
free(linkw);
|
||||
CloseHandle(hFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_tmp = php_win32_ioutil_conv_w_to_any(targetw, dwRet, &_tmp_len);
|
||||
if (!_tmp || _tmp_len >= MAXPATHLEN) {
|
||||
if(targetw_len > 4) {
|
||||
/* Skip first 4 characters if they are "\\?\" */
|
||||
if(targetw[0] == L'\\' && targetw[1] == L'\\' && targetw[2] == L'?' && targetw[3] == L'\\') {
|
||||
offset = 4;
|
||||
|
||||
/* \\?\UNC\ */
|
||||
if (targetw_len > 7 && targetw[4] == L'U' && targetw[5] == L'N' && targetw[6] == L'C') {
|
||||
offset += 2;
|
||||
targetw[offset] = L'\\';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = php_win32_ioutil_conv_w_to_any(targetw + offset, targetw_len - offset, &ret_len);
|
||||
if (!ret || ret_len >= MAXPATHLEN) {
|
||||
CloseHandle(hFile);
|
||||
free(linkw);
|
||||
return -1;
|
||||
}
|
||||
memcpy(target, _tmp, _tmp_len);
|
||||
free(_tmp);
|
||||
memcpy(target, ret, ret_len + 1);
|
||||
free(ret);
|
||||
|
||||
CloseHandle(hFile);
|
||||
free(linkw);
|
||||
|
||||
if(dwRet > 4) {
|
||||
/* Skip first 4 characters if they are "\??\" */
|
||||
if(target[0] == '\\' && target[1] == '\\' && target[2] == '?' && target[3] == '\\') {
|
||||
char tmp[MAXPATHLEN];
|
||||
unsigned int offset = 4;
|
||||
dwRet -= 4;
|
||||
|
||||
/* \??\UNC\ */
|
||||
if (dwRet > 7 && target[4] == 'U' && target[5] == 'N' && target[6] == 'C') {
|
||||
offset += 2;
|
||||
dwRet -= 2;
|
||||
target[offset] = '\\';
|
||||
}
|
||||
|
||||
memcpy(tmp, target + offset, dwRet);
|
||||
memcpy(target, tmp, dwRet);
|
||||
}
|
||||
}
|
||||
|
||||
target[dwRet] = '\0';
|
||||
return dwRet;
|
||||
return ret_len;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
50
ext/standard/tests/dir/bug73877.phpt
Normal file
50
ext/standard/tests/dir/bug73877.phpt
Normal file
|
@ -0,0 +1,50 @@
|
|||
--TEST--
|
||||
Bug #73877 readlink() returns garbage for UTF-8 paths
|
||||
File type functions
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (substr(PHP_OS, 0, 3) != 'WIN') {
|
||||
die('skip only for Windows');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$base = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug73877";
|
||||
$dir0 = $base . DIRECTORY_SEPARATOR . "bug73877";
|
||||
$dir1 = $base . DIRECTORY_SEPARATOR . "Серёжка";
|
||||
$junk0 = $base . DIRECTORY_SEPARATOR . "Серёжка2";
|
||||
|
||||
mkdir($base);
|
||||
mkdir($dir0);
|
||||
mkdir($dir1);
|
||||
`mklink /J $junk0 $dir0`;
|
||||
|
||||
var_dump(
|
||||
readlink($dir0),
|
||||
readlink($dir1),
|
||||
readlink($junk0),
|
||||
strlen(readlink($dir0)) === strlen(readlink($junk0))
|
||||
);
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
|
||||
$base = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug73877";
|
||||
$dir0 = $base . DIRECTORY_SEPARATOR . "bug73877";
|
||||
$dir1 = $base . DIRECTORY_SEPARATOR . "Серёжка";
|
||||
$junk0 = $base . DIRECTORY_SEPARATOR . "Серёжка2";
|
||||
|
||||
rmdir($junk0);
|
||||
rmdir($dir0);
|
||||
rmdir($dir1);
|
||||
rmdir($base);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(%d) "%sbug73877"
|
||||
string(%d) "%sСерёжка"
|
||||
string(%d) "%sbug73877"
|
||||
bool(true)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue