Refine fix for multibyte char hanling inside command names and args
この変更はマルチバイト圏のユーザーには厳しい予感がする(1・2・3)。
変更部分がphp_escape_shell_cmd関数内部とphp_escape_shell_arg関数内部なので、主にescapeshellcmd関数とescapeshellarg関数が影響を受けます。
どういう結果になるのか(一応)確認。
% cd /usr/local/src % gzip -dc php-5.2.5.tar.gz | gtar xf - % cd php-5.2.5 % ./configure \ --disable-all \ --without-iconv \ --enable-mbstring \ --enable-debug % make % cp sapi/cli/php /usr/local/src/php-5.2.5-cli % cd /usr/local/src % gzip -dc php5.2-200803250130.tar.gz | gtar xf - % cd php5.2-200803250130 % ./configure \ --disable-all \ --without-iconv \ --enable-mbstring \ --enable-debug % make % cp sapi/cli/php /usr/local/src/php-5.2.6-dev-cli-200803250130 % cd /usr/local/src % cat ./exec.php <?php declare( encoding="EUC-JP" ); var_dump( PHP_VERSION ); var_dump( escapeshellcmd( "/usr/local/src/あ" ) ); var_dump( escapeshellarg( "/usr/local/src/あ" ) ); var_dump( escapeshellcmd( "'/usr/local/src/あ'" ) ); var_dump( escapeshellarg( "'/usr/local/src/あ'" ) ); var_dump( escapeshellcmd( '"/usr/local/src/あ"' ) ); var_dump( escapeshellarg( '"/usr/local/src/あ"' ) ); var_dump( escapeshellcmd( "/usr/local/あ/src" ) ); var_dump( escapeshellarg( "/usr/local/あ/src" ) ); var_dump( escapeshellcmd( "'/usr/local/あ/src'" ) ); var_dump( escapeshellarg( "'/usr/local/あ/src'" ) ); var_dump( escapeshellcmd( '"/usr/local/あ/src"' ) ); var_dump( escapeshellarg( '"/usr/local/あ/src"' ) ); ?> % ./php-5.2.5-cli ./exec.php string(5) "5.2.5" string(17) "/usr/local/src/あ" string(19) "'/usr/local/src/あ'" string(19) "'/usr/local/src/あ'" string(27) "''\''/usr/local/src/あ'\'''" string(19) ""/usr/local/src/あ"" string(21) "'"/usr/local/src/あ"'" string(17) "/usr/local/あ/src" string(19) "'/usr/local/あ/src'" string(19) "'/usr/local/あ/src'" string(27) "''\''/usr/local/あ/src'\'''" string(19) ""/usr/local/あ/src"" string(21) "'"/usr/local/あ/src"'" % ./php-5.2.6-dev-cli-200803250130 ./exec.php string(12) "5.2.6RC3-dev" string(15) "/usr/local/src/" string(17) "'/usr/local/src/'" string(17) "'/usr/local/src/'" string(25) "''\''/usr/local/src/'\'''" string(17) ""/usr/local/src/"" string(19) "'"/usr/local/src/"'" string(15) "/usr/local//src" string(17) "'/usr/local//src'" string(17) "'/usr/local//src'" string(25) "''\''/usr/local//src'\'''" string(17) ""/usr/local//src"" string(19) "'"/usr/local//src"'" % uname -a Linux 2.6.18-6-686 #1 SMP Sun Feb 10 22:11:31 UTC 2008 i686 GNU/Linux
ぎゃっ。
ただ、理由も無しに変更するハズは無いので何かしらの理由がありそう(不正なマルチバイトによるセキュリティ対策とか)。
変更点を注意深く見てみると、php_mblen関数の結果如何で挙動が変わってきそうな雰囲気。
もうだけ少し深追い。
% cd /usr/local/src/php5.2-200803250130 % grep -rn php_mblen . ./NEWS:2424:- Fixed bug #35243 (php_mblen() crashes when compiled with thread-safety on ./ext/standard/string.c:1366: inc_len = (*c == '\0' ? 1: php_mblen(c, cnt)); ./ext/standard/string.c:1372: php_mblen(NULL, 0); ./ext/standard/exec.c:276: int mb_len = php_mblen(str + x, (l - x)); ./ext/standard/exec.c:358: int mb_len = php_mblen(str + x, (l - x)); ./ext/standard/file.c:1884: inc_len = (*ptr == '\0' ? 1: php_mblen(ptr, len)); ./ext/standard/file.c:1889: php_mblen(NULL, 0); ./ext/standard/file.c:2119: php_mblen(NULL, 0); ./ext/standard/file.c:2147: inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0); ./ext/standard/file.c:2152: php_mblen(NULL, 0); ./ext/standard/file.c:2239: php_mblen(NULL, 0); ./ext/standard/file.c:2294: inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0); ./ext/standard/file.c:2307: php_mblen(NULL, 0); ./ext/standard/file.c:2318: inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0); ./ext/standard/file.c:2338: php_mblen(NULL, 0); ./ext/standard/file.c:2349: inc_len = (bptr < limit ? (*bptr == '\0' ? 1: php_mblen(bptr, limit - bptr)): 0); ./ext/standard/php_string.h:150:# define php_mblen(ptr, len) 1 ./ext/standard/php_string.h:153:# define php_mblen(ptr, len) ((ptr) == NULL ? mbsinit(&BG(mblen_state)): (int)mbrlen(ptr, len, &BG(mblen_state))) ./ext/standard/php_string.h:155:# define php_mblen(ptr, len) mblen(ptr, len) % less -N ./ext/standard/php_string.h 〜 省略 〜 149 #ifndef HAVE_MBLEN 150 # define php_mblen(ptr, len) 1 151 #else 152 # if defined(_REENTRANT) && defined(HAVE_MBRLEN) && defined(HAVE_MBSTATE_T) 153 # define php_mblen(ptr, len) ((ptr) == NULL ? mbsinit(&BG(mblen_state)): (int)mbrlen(ptr, len, &BG(mblen_state))) 154 # else 155 # define php_mblen(ptr, len) mblen(ptr, len) 156 # endif 157 #endif 〜 省略 〜 % grep -n HAVE_MBLEN ./main/php_config.h 358:#define HAVE_MBLEN 1 % grep -n HAVE_MBRLEN ./main/php_config.h 361:#define HAVE_MBRLEN 1 % grep -n HAVE_MBSTATE_T ./main/php_config.h 2653:#define HAVE_MBSTATE_T 1 % grep -rn _REENTRANT . ./configure:12662: PTHREAD_FLAGS="-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT";; ./configure:12664: PTHREAD_FLAGS="-D_REENTRANT -D_THREAD_SAFE";; ./configure:12666: PTHREAD_FLAGS=-D_REENTRANT;; ./configure:12672: PTHREAD_FLAGS=-D_REENTRANT;; ./configure:12674: PTHREAD_FLAGS=-D_REENTRANT;; ./configure:18716:#define _REENTRANT ./configure:18752:#define _REENTRANT ./configure:18906:#define _REENTRANT 1 ./configure:18930:#define _REENTRANT 1 ./configure:18955:#define _REENTRANT 1 ./aclocal.m4:1337:#define _REENTRANT ./aclocal.m4:1361:#define _REENTRANT ./aclocal.m4:2770:#define _REENTRANT 1 ./aclocal.m4:2780:#define _REENTRANT 1 ./aclocal.m4:2791:#define _REENTRANT 1 ./ext/standard/php_string.h:152:# if defined(_REENTRANT) && defined(HAVE_MBRLEN) && defined(HAVE_MBSTATE_T) ./ext/standard/basic_functions.h:215:#if defined(_REENTRANT) && defined(HAVE_MBRLEN) && defined(HAVE_MBSTATE_T) ./ext/standard/basic_functions.c:3916:#if defined(_REENTRANT) && defined(HAVE_MBRLEN) && defined(HAVE_MBSTATE_T) ./ext/standard/crypt.c:151:#if defined(HAVE_CRYPT_R) && (defined(_REENTRANT) || defined(_THREAD_SAFE)) ./acinclude.m4:1337:#define _REENTRANT ./acinclude.m4:1361:#define _REENTRANT ./acinclude.m4:2770:#define _REENTRANT 1 ./acinclude.m4:2780:#define _REENTRANT 1 ./acinclude.m4:2791:#define _REENTRANT 1 ./sapi/roxen/roxen.c:114:#if defined(_REENTRANT) && !defined(ROXEN_USE_ZTS) ./sapi/roxen/roxen.c:123:#else /* !_REENTRANT */ ./sapi/roxen/roxen.c:128:#endif /* _REENTRANT */ ./TSRM/threads.m4:42: PTHREAD_FLAGS="-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT";; ./TSRM/threads.m4:44: PTHREAD_FLAGS="-D_REENTRANT -D_THREAD_SAFE";; ./TSRM/threads.m4:46: PTHREAD_FLAGS=-D_REENTRANT;; ./TSRM/threads.m4:52: PTHREAD_FLAGS=-D_REENTRANT;; ./TSRM/threads.m4:54: PTHREAD_FLAGS=-D_REENTRANT;; ./TSRM/threads.m4:56:dnl PTHREAD_FLAGS="-D_REENTRANT -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=199506 -D_XOPEN_SOURCE_EXTENDED=1";;
155行目が有効になっている。。。と。で、mblen関数はlocaleに依存する。。。と。_| ̄|○
もし、mblen関数が腐った実装だったら。。。ひぇ。
それにしても、今後はlocaleに注意しながら実装しないといけないの?うーん。