PHPの動的キャストで完全にハマった
[ PR ]
今日、漢字辞典『さくら』に新しい機能を追加したのですが、その適用の際にサーバ上でバグが起こってしまい、完全にサービスを止めてしまいました。
動的キャストの罠
ハマった原因は、動的キャストによるものでした。
ここでいう動的キャストとは、例えば '103'
という文字列が 103
という数値に暗黙にキャストされることです。
mysqli_connect でハマった
具体的にハマったのは次のような感じです。
// 正しい?
mysqli_connect("localhost","mysql_user","aaaa","db","3000");
一見正しいように見えます。それどころか、正しく動きます。
ですが、次の例はエラーになります。
// エラー
mysqli_connect("localhost","mysql_user","aaaa","db","");
どうしてでしょうか? …実は最後の引数(ポート)は正しくは整数です。
要するに、"3000"
は正しく3000
に変換され、""
はnull
に変換されるということです。
検証とPHPの限界
つまり最初を辿ると、自分が定義を間違えていたということです。
ですが、解決できるまでの時間を長期化したのは、全く問題箇所に気付けなかったという点です。
引数の扱い
気付かなかった原因の1つはエラーの内容にあります。
mysqli_connect() expects parameter 5 to be long
まるでそもそも5番目の引数なんてなかったかのようなエラーメッセージです。
PHPは元々引数の扱いが曖昧で、引数の数はチェックされません。
バージョン間の差異
さらにもうひとつ問題なのが、PHPのバージョンによってはエラーにならないという点です。
これは勘違いかもしれませんが、手元のPHPではエラーになりませんでした。
このことには動的キャストに関する根深い問題があります。動的キャストはその変換が分かりづらく、今回のようなケースが多くおこりがちです。
特に今回の場合はどんなテストを書いたとしても、MySQLのログインの問題という基礎的な箇所なので、より気づきにくかったと思います。
ちなみに、実はPHPにもSTRICTかどうかチェックする機能があるのですが、今回は使っていなかったため、果たして暗黙のキャストまでチェックするのかどうかは検証できていません。
error_reporting(E_NOTICE|E_STRICT);
まとめ
PHPにはこのような根深い問題がいくつかあります。
これらの問題がSTRICTで解消できれば安心できますが、未検証のためわかりません。
それか、型に厳密なHaxeのようなトランスレータ言語からPHPを生成するというのも1つの手かもしれませんね。
技術評論社
売り上げランキング: 13,330