Bug #74589 [Com]: __DIR__ wrong for unicode character

From: Date: Sun, 14 May 2017 20:31:51 +0000
Subject: Bug #74589 [Com]: __DIR__ wrong for unicode character
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-209116@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=74589&edit=1 ID: 74589 Comment by: ganlvtech at qq dot com Reported by: ganlvtech at qq dot com Summary: __DIR__ wrong for unicode character Status: Feedback Type: Bug Package: *General Issues Operating System: Windows PHP Version: 7.1.5 Block user comment: N Private report: N New Comment: Probably reason. When php core get the filename from system, my system returns a string with cp 936. Because php5 doesn't auto convert charset, so the strlen and mb_strlen is both 22 (one chinese character is two bytes). But php7 convert charset automatically, so strlen is 27(1 char for 3 bytes in UTF-8) and mb_strlen is 17. And zend_dirname function use a macro IS_SLASH_P, and the macro call a WIN32API IsDBSCLeadByte. For cp936(GBK), the chinese character's two bytes is both larger than 0x80, IsDBSCLeadByte always return non-zero, even when testing the second byte. In php7, dirname(__FILE__) passed a converted, UTF-8 string to zend_dirname, so it works well. But there might not be a automatically conversion in the zend engine when directily using __DIR__. In php5 conversion will never automatically apply, so the two forms both don't work. Summary: Everything is caused by my system's returning bp936(GBK) encoded path. This may not be a bug of php, but it should be metioned in php docs. Thanks. Previous Comments: ------------------------------------------------------------------------ [2017-05-14 19:33:44] ganlvtech at qq dot com <?php echo __FILE__, "\n"; echo strlen(__FILE__), "\n"; echo mb_strlen(__FILE__), "\n"; ?> (php 7.1, cp 936) D:\新建文件夹>php test.php D:\新建文件夹\test.php 27 17 (php 5.4, cp 936) D:\新建文件夹>php54 test.php D:\新建文件夹\test.php 22 22 ------------------------------------------------------------------------ [2017-05-14 18:16:11] ganlvtech at qq dot com I tested GBK and UTF-8 as default_charset and php 5.4, 5.6 and 7.1. Test Report: php: 5.4 or 5.6 default_charset: GBK or UTF-8 Results: D:\ D:\ bool(true) ----- php: 7.1 default_charset: GBK or UTF-8 Results: D:\ D:\新建文件夹 bool(false) ===== CJK charchter and even \u00a1 may cause a wrong result. Seems that, only if trailing charchter is an ASCII character, the result can be correct. ===== Hope that the tests above can help you. Thanks. ------------------------------------------------------------------------ [2017-05-14 17:52:27] ganlvtech at qq dot com php.ini is php.ini-development default_charset => UTF-8 => UTF-8 internal_encoding => no value => no value zend.multibyte => Off => Off PHP version: PHP 7.1.5 (cli) (built: May 9 2017 19:48:36) ( NTS MSVC14 (Visual C++ 2015) x64 ) System: Windows 10 Home (64bit). (x64 processor) Default language: zh-CN (There is no other system language supported in my system. My system cannot switch into English mode) Default code page: 936(GBK) I tried chcp 65001 or chcp 437, it makes no changes. ===== I have tried in Interactive shell. It seems working correctly. D:\新建文件夹>php -a Interactive shell php > echo __FILE__; php shell code php > echo __DIR__; D:\新建文件夹 ===== I have also tried php 5.4 or php 5.6 (both are use php.ini-development) "D:\新建文件夹\test.php" shows (different from php7) D:\ D:\ bool(true) So, i tried Script: <?php echo __DIR__, "\n"; echo dirname(__FILE__), "\n"; var_dump(__DIR__ === dirname(__FILE__)); echo __FILE__, "\n"; echo str_replace('\\', '/', __FILE__), "\n"; echo dirname(str_replace('\\', '/', __FILE__)), "\n"; ?> Result: (php 5.4) D:\ D:\ bool(true) D:\新建文件夹\test.php D:/新建文件夹/test.php D:/新建文件夹 ===== Anything works well on Ubuntu Server 16.04 (php7.0 and php5.5 were tested). I think it may be caused by backslash. ------------------------------------------------------------------------ [2017-05-14 14:37:47] ab@php.net Thanks for the report. Please post additionally - default_charset INI - internal_encoding INI - whether zend_multibyte is used - whether your're on a DBCS system, codepage 932, 936 or alike I have to say, that so far i've tried the snippet on a cp 437 system with default php.ini settings, i see it working correctly. I guess, that there can be an issue with a particular system codepage and non UTF-8 settings in php.ini, would be nice you to do a bit more research in this direction. Thanks. ------------------------------------------------------------------------ [2017-05-14 07:07:24] ganlvtech at qq dot com Description: ------------ Save the test script to "D:\新建文件夹\test.php".(There must be some unicode character in the path) Then execute php test.php. On Windows, shows D:\ D:\新建文件夹 bool(false) Save to "D:\新建文件夹a\test.php", then shows D:\新建文件夹a D:\新建文件夹a bool(true) Save to "D:\a新建文件夹\test.php", then shows D:\ D:\a新建文件夹 bool(false) Save to "D:\a新建文件夹\a新建文件夹\test.php", then shows D:\ D:\a新建文件夹\a新建文件夹 bool(false) So, you may find that. If the directory's name ends with a unicode character, then __DIR__ would miss this part, until it find a dir not ends with a unicode character. Sorry for my poor English. Test script: --------------- <?php echo __DIR__, "\n"; echo dirname(__FILE__), "\n"; var_dump(__DIR__ === dirname(__FILE__)); ?> ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=74589&edit=1

« previous php.bugs (#209116) next »