2012-02-23 :-(
_ [Shift_JIS][0x5C][バックスラッシュ]0x5C
上司からクイズを貰った。
以下のコードをコンパイルして実行するとどうなるか。start を印字して終了することを期待する。
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { //危ないんだよ int is_dangerous = 1; //始めるのだぁ printf("start\n"); //危ない場合は止めるの― if (is_dangerous) exit(-1); //安全なので動かすなりっ printf("move\n"); return 0; }
% gcc --version gcc (GCC) 4.5.3
% gcc bug0.c && ./a.exe start move
if はどこに行った。
アセンブルしてみた。
% gcc -S bug0.c
.file "bug0.c" .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC0: .ascii "start\0" LC1: .ascii "move arm\0" .text .globl _main .def _main; .scl 2; .type 32; .endef _main: pushl %ebp movl %esp, %ebp andl $-16, %esp subl $32, %esp call ___main movl $1, 28(%esp) ← たぶん is_dangerous = 1; の処理 movl $LC0, (%esp) call _puts movl $LC1, (%esp) call _puts movl $0, %eax leave ret .def _puts; .scl 2; .type 32; .endef
アセンブリなんてよく分からないけど test とかそういう類の命令が見当たらない。たしかに if が無くなったようだ。
なんとなくコメントを削除して再度コンパイルして実行してみた。
% ./a.exe start
if が処理されたようだ。
削除したコメントを戻し、ファイルのエンコードを UTF-8 に変換してから( いままで Shift_JIS だった )コンパイルして実行してみた。
% ./a.exe start
if が処理されたようだ。
0x5C
Shift_JIS - 2バイト目が5C等になりうることによる問題
Shift_JISでは、「ソ」「噂」など一部の字の2バイト目に、5C(Shift_JISでは¥記号、ASCIIなどではバックスラッシュ)を使用している。多くのプログラミング言語 (C、Perl、Bourne Shellなど多数) では、この5Cをエスケープ文字としている。したがって、ソースコードや文字データの処理においてShift_JISを想定していないプログラミング環境では問題が起こる。この問題は、同じように2バイト目の範囲に5Cを含むBig5や、まれではあるがGBKなどの文字コードでも発生しうる。
バックスラッシュとして解釈されてしまい、続く行がコメントとして解釈されてしまうらしい。
ソースコードをバイナリエディタで眺めてみたら 81 5C (―ダッシュ)があった。なるほど
[ツッコミを入れる]