【php】やってしまうと見つけにくい不具合
問題
↓ これは普通の結果ですが…
$ php -r 'var_dump(1 > 2);' bool(false)
↓ これはどうしたことでしょう?
$ php -r 'var_dump(1 > 2);' bool(true)
答え
問題のスクリプトは、以下と似たような事態。2の前に全角スペースが入っている。
$ php -r 'var_dump(1 > ■2);' bool(true) $ php -r 'var_dump(1 > aa2);' bool(true) $ php -r 'var_dump(1 > 全角スペース2);' bool(true)
以下の3点から、結果としてそうなる。
-
マルチバイト文字であっても、変数名、定数名、関数名に使えること。
文字またはアンダースコアから始まり、任意の数の文字、 数字、アンダースコアが続きます。正規表現によれば、これは次の ように表現することができます。 ‘[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*’
http://jp2.php.net/manual/ja/language.constants.php
-
未定義の定数を使用したときの振る舞い。
未定義の定数を使用した場合、ちょうどstringとして コールしたかのように(CONSTANT vs “CONSTANT”)、 PHPはその定数自体の名前を使用したと仮定します。 この際、E_NOTICE が発生します。
-
自動的な型変換。
http://jp2.php.net/manual/ja/language.types.type-juggling.php
いろいろな例
「 2(全角スペースと2)」が未定義の定数として評価され、文字列” 2″となり、数字との比較で数字に変換されて、0となるため、「1 > 2」→ 「1 > 0」 → true となる。
うっかり変なところに全角スペースを入れてしまうと、見えないし、構文エラーにもならなくて(Noticeなら発生するが)、発見しづらい。
$ php -r 'var_dump(1 > 2);' bool(true)
「 2(全角スペースと2)」で定数を定義できる。使用もできる。
# php -r 'define(' 2', 5); var_dump(1 > 2);' bool(false)
ドル記号と変数名の間に全角スペースがあっても、構文は間違っていないので動く。さすがにこれは見て気づくと思うけど。
$ php -r '$a = 2; var_dump(1 > $ a);' bool(true)
でもやっぱり、こういうことをしてしまうと見つけにくい($a代入時の2の前に全角スペース)。
$ php -r '$a = 2; var_dump(1 > $a);' bool(true)
おばけのような全角スペースの話でした。
phpでは「全角の文字でも定数に使えるよ! & 未定義の定数は文字列扱いされるから気をつけてね!」ということで。
コメント