Jcode::getcode は UTF-8 な文字列のエンコード方式判定に失敗することがある。
Jcode::convert を使ったプログラムで、次のようなエラーが出ることがある。
Use of uninitialized value in string eq at /usr/lib/perl5/site_perl/5.8.2/i386-linux-thread-multi/Jcode.pm line 625, <> line 10. Use of uninitialized value in pattern match (m//) at /usr/lib/perl5/site_perl/5.8.2/i386-linux-thread-multi/Jcode.pm line 632, <> line 10.
ちなみに line 632 ってのは Jcode.pm の行番号、 "<> line 10" ってのは、標準入力からの入力の 10 行目まで読んだところでエラー、という意味 *1。
Jcode.pm の 632 行目は……
load_module("Jcode::Unicode") if $icode =~ /ucs2|utf8/o;
「ここで uninitialized value が pattern match に使われているぞ」というエラーだから…… $icode が undef になってるってことだろう。 $icode には Jcode::getcode() の戻り値が入っている(623 行目)。ということは、文字コードの判定が上手くいっていないということか。
対象のエラーが出た行を絞り込むと、どうやら Google 検索で " sshd Illegal user 回数" と検索してきたらしい。 "回数" は "%E5%9B%9E%E6%95%B0" とエンコードされていた。
これをバイナリエディタでファイルに書くと、 lv で読めて less で読めない。 lv が言うには UTF-8 らしい。
こいつを Jcode::getcode() に掛けるとやはり undef が返ってくる。
というわけで、漢字コードの変換を「getcode して undef だったら UTF-8 と決め打ち」という方針にすることに。それ以外のエンコードでも多分読めないだろうしね。
convert() に変換前文字コードを明示的に指定すれば処理速度も問題なし。
*1:今回のコードでは入力を全部読んでから処理をしているので、この行番号にはあまり意味がない