トップ «前の日記(2012-02-22) 最新 次の日記(2012-02-24)» 編集

ヨタの日々

2001|08|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|12|
2024|01|02|03|04|

2012-02-23 :-(

_ 午前

0520 起床

0830 出勤

0900 テスト

_ 午後

1300 テスト

1700 退勤

_

1900 gccほげ

2130 飯。メカジキのムニエル

_ [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 (―ダッシュ)があった。なるほど

b00.png