てきとうなさいと べぇたばん

PHP 7.3.0がリリースされた - はじめてのバグ報告 -

Changelogに載ってしまった report a bugページ。

PHP 7.3.0

PHPの7.3.0がリリースされた。めでたい🎉

バグを見つける

実は、この7.3.0のリリースの直前のRC5で、一つバグを見つけてしまった。mb_check_encoding関数(とmb_convert_encoding関数)に空の配列を引数にとるとSegmentation faultになるという問題。

PHPの互換性を調べるのに役立つ3v4l.orgでも"Process exited with code 139."となって、手元のLinux環境でコンパイルして調べたらSegmentation faultになった。exit codeが139というのは、SIGSEGVなので、3v4lでもSegmentation faultになってたわけである。

最初、Twitterでも募ってみたけど、特に既知だったということはないみたいだ。誰も知らないバグだったようだと判断して、バグ報告しようと決意する。

報告への迷い

もちろん、迷いはまだあったので、報告をするための情報を集めることにした。まずは、PHPのバグ報告のページ。

PHP のバグを発見した場合は、報告してください。あなたがそのバグを報告しない限り、 PHP の開発者がそのバグを知ることは恐らくなく、修正されることもないでしょう。

バグは報告しないと修正されない

報告した先人

報告をした方々のエントリもあるので見てみる。

英語でひるむのはもったいない。どうせコードと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

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());
mb_check_encodingの返り値
PHP 5.6PHP 7.0 7.1PHP 7.2 or greater
FALSENULLTRUE

感想

複雑に色々な感情が降り混ってる。

  • 本当に修正されてしまった
  • 私が踏んだバグを世界中の人々が踏まなくて済む
  • NEWSに私の文章が乗っかってしまった
  • 15分で修正されたのすごい
  • まだバグ1件だけ報告しただけだけどな
  • やはり英語勉強しないとなー