]> granicus.if.org Git - php/commitdiff
Fixed bug #75063
authorAnatol Belski <ab@php.net>
Sun, 13 Aug 2017 22:44:19 +0000 (00:44 +0200)
committerAnatol Belski <ab@php.net>
Sun, 13 Aug 2017 22:44:19 +0000 (00:44 +0200)
Zend/zend.c
Zend/zend_virtual_cwd.c
Zend/zend_virtual_cwd.h
ext/standard/tests/file/windows_mb_path/bug75063_cp1251.phpt [new file with mode: 0644]
ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt [new file with mode: 0644]
main/main.c

index 282ad018db9e079e2306ed2731f954e001505e61..dbda7091986791a0bd08ab81c61fba07f3bb2fcd 100644 (file)
@@ -660,6 +660,10 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
        extern zend_php_scanner_globals language_scanner_globals;
 #endif
 
+#ifdef ZEND_WIN32
+       php_win32_cp_set_by_id(65001);
+#endif
+
        start_memory_manager();
 
        virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */
index c42739a7442b965580f678783f73016235778c16..2fa12f81808e9dbaae5aa638b851b93c9541a520 100644 (file)
@@ -445,11 +445,15 @@ static void cwd_globals_dtor(virtual_cwd_globals *cwd_g) /* {{{ */
 }
 /* }}} */
 
-CWD_API void virtual_cwd_startup(void) /* {{{ */
+void virtual_cwd_main_cwd_init(uint8_t reinit) /* {{{ */
 {
        char cwd[MAXPATHLEN];
        char *result;
 
+       if (reinit) {
+               free(main_cwd_state.cwd);
+       }
+
 #ifdef NETWARE
        result = getcwdpath(cwd, NULL, 1);
        if(result)
@@ -461,10 +465,10 @@ CWD_API void virtual_cwd_startup(void) /* {{{ */
                        ++c;
                }
        }
-#else
-#ifdef ZEND_WIN32
+#elif defined(ZEND_WIN32)
        ZeroMemory(&cwd, sizeof(cwd));
-#endif
+       result = php_win32_ioutil_getcwd(cwd, sizeof(cwd));
+#else
        result = getcwd(cwd, sizeof(cwd));
 #endif
        if (!result) {
@@ -478,7 +482,12 @@ CWD_API void virtual_cwd_startup(void) /* {{{ */
        }
 #endif
        main_cwd_state.cwd = strdup(cwd);
+}
+/* }}} */
 
+CWD_API void virtual_cwd_startup(void) /* {{{ */
+{
+       virtual_cwd_main_cwd_init(0);
 #ifdef ZTS
        ts_allocate_id(&cwd_globals_id, sizeof(virtual_cwd_globals), (ts_allocate_ctor) cwd_globals_ctor, (ts_allocate_dtor) cwd_globals_dtor);
 #else
index 9a7a1efc7269559777e985b6582db2846aaaa327..36ff44c4d0612322a1a2a96a9e9ed078d4e4abf6 100644 (file)
@@ -251,6 +251,10 @@ CWD_API zend_long realpath_cache_size(void);
 CWD_API zend_long realpath_cache_max_buckets(void);
 CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void);
 
+#ifdef CWD_EXPORTS
+extern void virtual_cwd_main_cwd_init(uint8_t);
+#endif
+
 /* The actual macros to be used in programs using TSRM
  * If the program defines VIRTUAL_DIR it will use the
  * virtual_* functions
diff --git a/ext/standard/tests/file/windows_mb_path/bug75063_cp1251.phpt b/ext/standard/tests/file/windows_mb_path/bug75063_cp1251.phpt
new file mode 100644 (file)
index 0000000..1c890ed
--- /dev/null
@@ -0,0 +1,80 @@
+--TEST--
+Bug #75063 Many filesystem-related functions do not work with multibyte file names, cp1251
+--SKIPIF--
+<?php
+include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc";
+
+skip_if_not_win();
+if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+skip_if_no_required_exts();
+
+?>
+--INI--
+default_charset=cp1251
+--FILE--
+<?php
+
+/* This file is in cp1251. */
+
+include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc";
+
+$dir_basename = "òåñò";
+$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-cp1251";
+$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename;
+
+mkdir($prefix);
+create_verify_dir($prefix, $dir_basename, 1251);
+
+var_dump(get_basename_with_cp($d0, 1251, false));
+
+$old_cwd = getcwd();
+var_dump(chdir($d0));
+
+$code = <<<CODE
+<?php
+
+foreach(["test", "òàñò"] as \$fn) {
+       file_put_contents("\$fn.txt", "");
+}
+
+var_dump(getcwd());
+if (\$dh = opendir(getcwd())) {
+       while ((\$file = readdir(\$dh)) !== false) {
+               if ("." == \$file || ".." == \$file) continue;
+               var_dump(\$file);
+       }
+       closedir(\$dh);
+}
+CODE;
+$code_fn = "code.php";
+file_put_contents($code_fn, $code);
+
+print(shell_exec(getenv('TEST_PHP_EXECUTABLE') . " -n -d default_charset=cp1251 -f code.php"));
+
+chdir($old_cwd);
+
+/* --CLEAN-- section were the right place, but it won't accept default_charset ATM, it seems. */
+$dir_basename = "òåñò";
+$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-cp1251";
+$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename;
+
+$obj = scandir($d0);
+foreach ($obj as $file) {
+       if ("." == $file || ".." == $file) continue;
+       unlink($d0 . DIRECTORY_SEPARATOR . $file);
+}
+
+rmdir($d0);
+rmdir($prefix);
+?>
+===DONE===
+
+--EXPECTF--
+string(4) "òåñò"
+bool(true)
+string(%d) "%sbug75063-cp1251%eòåñò"
+string(8) "code.php"
+string(8) "test.txt"
+string(8) "òàñò.txt"
+===DONE===
+
diff --git a/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt b/ext/standard/tests/file/windows_mb_path/bug75063_utf8.phpt
new file mode 100644 (file)
index 0000000..b4a59d1
--- /dev/null
@@ -0,0 +1,81 @@
+--TEST--
+Bug #75063 Many filesystem-related functions do not work with multibyte file names, UTF-8
+--SKIPIF--
+<?php
+include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc";
+
+skip_if_not_win();
+if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+skip_if_no_required_exts();
+
+?>
+--FILE--
+<?php
+
+/* This file is in UTF-8. */
+
+include dirname(__FILE__) . DIRECTORY_SEPARATOR . "util.inc";
+
+$dir_basename = "тест";
+$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-utf8";
+$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename;
+
+mkdir($prefix);
+create_verify_dir($prefix, $dir_basename);
+
+var_dump(get_basename_with_cp($d0, 65001, false));
+
+$old_cwd = getcwd();
+var_dump(chdir($d0));
+
+$code = <<<CODE
+<?php
+
+foreach(["test", "таст"] as \$fn) {
+       file_put_contents("\$fn.txt", "");
+}
+
+var_dump(getcwd());
+if (\$dh = opendir(getcwd())) {
+       while ((\$file = readdir(\$dh)) !== false) {
+               if ("." == \$file || ".." == \$file) continue;
+               var_dump(\$file);
+       }
+       closedir(\$dh);
+}
+CODE;
+$code_fn = "code.php";
+file_put_contents($code_fn, $code);
+
+print(shell_exec(getenv('TEST_PHP_EXECUTABLE') . " -nf code.php"));
+
+chdir($old_cwd);
+
+?>
+===DONE===
+--CLEAN--
+<?php
+$dir_basename = "тест";
+$prefix = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug75063-utf8";
+$d0 = $prefix . DIRECTORY_SEPARATOR . $dir_basename;
+
+$obj = scandir($d0);
+foreach ($obj as $file) {
+       if ("." == $file || ".." == $file) continue;
+       unlink($d0 . DIRECTORY_SEPARATOR . $file);
+}
+
+rmdir($d0);
+rmdir($prefix);
+
+?>
+
+--EXPECTF--
+string(8) "тест"
+bool(true)
+string(%d) "%sbug75063-utf8%eтест"
+string(8) "code.php"
+string(8) "test.txt"
+string(12) "таст.txt"
+===DONE===
+
index f812b33e669b3f750c1f433fccb500952c9c7269..60b5f620a8fe617b7e7114588aef3f72f39753a4 100644 (file)
@@ -2221,6 +2221,20 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
        /* Register Zend ini entries */
        zend_register_standard_ini_entries();
 
+#ifdef ZEND_WIN32
+       /* Until the current ini values was setup, the current cp is 65001.
+               If the actual ini vaues are different, some stuff needs to be updated.
+               It concerns at least main_cwd_state and there might be more. As we're
+               still in the startup phase, lets use the chance and reinit the relevant
+               item according to the current codepage. Still, if ini_set() is used
+               later on, a more intelligent way to update such stuff is needed.
+               Startup/shutdown routines could involve touching globals and thus
+               can't always be used on demand. */
+       if (!php_win32_cp_use_unicode()) {
+               virtual_cwd_main_cwd_init(1);
+       }
+#endif
+
        /* Disable realpath cache if an open_basedir is set */
        if (PG(open_basedir) && *PG(open_basedir)) {
                CWDG(realpath_cache_size_limit) = 0;