PHP 7.3.0がリリースされた - はじめてのバグ報告 -
TOP > てきとうにこらむ > プログラミング日記 > PHP 7.3.0がリリースされた - はじめてのバグ報告 -
PHP 7.3.0
PHPの7.3.0がリリースされた。めでたい🎉
バグを見つける
実は、この7.3.0のリリースの直前のRC5で、一つバグを見つけてしまった。mb_check_encoding関数(とmb_convert_encoding関数)に空の配列を引数にとるとSegmentation faultになるという問題。
オーマイガー、PHP 7.3RC5のバグを踏んだらしい
— てきめん (@youkidearitai) 2018年11月15日
PHPの互換性を調べるのに役立つ3v4l.orgでも"Process exited with code 139."となって、手元のLinux環境でコンパイルして調べたらSegmentation faultになった。exit codeが139というのは、SIGSEGVなので、3v4lでもSegmentation faultになってたわけである。
最初、Twitterでも募ってみたけど、特に既知だったということはないみたいだ。誰も知らないバグだったようだと判断して、バグ報告しようと決意する。
PHP 7.3RC5のLinuxで以下がsegfaultするんですけど、Macだとしなかったんですが、これって既知ですか?
— てきめん (@youkidearitai) 2018年11月15日
var_dump(mb_check_encoding(array(), "UTF-8"));
報告への迷い
もちろん、迷いはまだあったので、報告をするための情報を集めることにした。まずは、PHPのバグ報告のページ。
PHP のバグを発見した場合は、報告してください。あなたがそのバグを報告しない限り、 PHP の開発者がそのバグを知ることは恐らくなく、修正されることもないでしょう。
バグは報告しないと修正されない。
報告した先人
報告をした方々のエントリもあるので見てみる。
- https://hnw.hatenablog.com/entry/20081022 hnwさんの記事めっちゃわかりやすい
 - http://d.hatena.ne.jp/shimooka/20081012/1223784788 shimookaさんの記事も勇気を貰える、コメント欄も読むべき
 
英語でひるむのはもったいない。どうせコードとTest script、Expected result、Actual resultが揃ってしまえば大抵は通じる。
既存のバグではないことを確認する
PHPのバグ追跡システム https://bugs.php.net/ で、このバグがすでに報告されているバグかどうかを調べる。mbstring crashとか、mb_check_encodingとかで調べてみたけど、すでにcloseされてたりしてたので重複はなかったみたいだった。
報告をする
2時間くらい悩んでSummaryとDescriptionを書き、Test scriptと、Actual result(現在の結果: つまりSegmentation fault)を埋めた。
- PHP versionはもちろんPHP 7.3.0 RC5
 - Package affectedに"General Issues"と"Reproducible crash"(再現性のあるクラッシュ)を選択
 - Bug Typeはもちろん"Bug"
 - Operating systemにはLinuxと入れた
 
Expected resultについて
のこりはExpected result(本来の結果)なんだけど、これを調べるのが実は大変だった。
最初、mb_check_encodingは空のarrayを加えるとNULLになると思っていたのだけど、3v4lの結果からPHP 7.2からはbool(true)に変更されていたことに気がついた。 mb_check_encodingのマニュアルには$varが文字列(string)だったのだから、E_WARNINGを発行したNULLが返ってくるものだと思いこんでた。
これは一体どういうことだということで、ext/mbstring/mbstring.cを見ると、なんか配列が受け付けられているような気がする。https://github.com/php/php-src/blob/php-7.3.0RC5/ext/mbstring/mbstring.c#L4813
switch(Z_TYPE_P(input)) {
    case IS_LONG:
    case IS_DOUBLE:
    case IS_NULL:
    case IS_TRUE:
    case IS_FALSE:
        RETURN_TRUE;
        break;
    case IS_STRING:
        if (!php_mb_check_encoding(Z_STRVAL_P(input), Z_STRLEN_P(input), enc ? ZSTR_VAL(enc): NULL)) {
            RETURN_FALSE;
        }
        break;
    case IS_ARRAY:
        if (!php_mb_check_encoding_recursive(HASH_OF(input), enc)) {
            RETURN_FALSE;
        }
        break;
    default:
        php_error_docref(NULL, E_WARNING, "Input is something other than scalar or array");
        RETURN_FALSE;
} 
ということで、Changelogを見てみると、PHP 7.2.0で以下を発見する。http://www.php.net/ChangeLog-7.php#7.2.0
- Added array input support to mb_convert_encoding().
 - Added array input support to mb_check_encoding().
 
つまり、mb_check_encodingは引数に配列を受け入れられるようになっていて、空の配列をmb_check_encodingの$varに入れると、エンコーディングには問題がないので、bool(true)となるように変更されたということのようだ。
ということで、このExpected resultには、bool(true)が正しいと考えたので、bool(true)を埋めることにした。
Submitを押す
何回かPreviewしてみたあとで、報告したのが以下。
PHP :: Bug #77165 :: mb_check_encoding crashes when argument given an empty array
この件、バグとして送りました。https://t.co/3rTT769nlc 英語おかしいのはごめんなさいって送りました。 https://t.co/IVeO1Ms3n0
— てきめん (@youkidearitai) 2018年11月15日
Submitを押したあと、日本時間では午前1時くらいだったから、その後で風呂はいって出てきたあとにまたこの画面をみると、「Status: Closed」となってた。
なんかまずかったかなと思って見てみたら、バグが修正されてた。mb_convert_encodingも同じバグがあったので、合わせて修正されてた。たった15分足らずで修正するのすごい…
まとめ
- mb_check_encodingとmb_convert_encodingはPHP 7.2からarrayが受け付けられるようになっている
 - PHP 7.3.0 RC5までその2つの関数でバグがあったので報告した
 
mb_check_encodingは、以下のコードでバージョンが違うだけで正反対の値が返ってくることになるので気をつけたほうがいいかもしれない
mb_check_encoding(array());
| PHP 5.6 | PHP 7.0 7.1 | PHP 7.2 or greater | 
|---|---|---|
| FALSE | NULL | TRUE | 
感想
複雑に色々な感情が降り混ってる。
- 本当に修正されてしまった
 - 私が踏んだバグを世界中の人々が踏まなくて済む
 - NEWSに私の文章が乗っかってしまった
 - 15分で修正されたのすごい
 - まだバグ1件だけ報告しただけだけだ
 - やはり英語勉強しないとなー
 



















