LATIN SMALL LETTER G WITH CEDILLA

  1. 環境は Plamo Linux 5.0, glibc-2.16.0, GNU grep 2.14, LANG=ja_JP.eucJP。
  2. grep -ir でディレクトリ全体を大文字小文字の区別なしで検索すると、SEGV することがある。
  3. どうもバイナリファイルでエラーになるようだ。
    1. バイナリファイルを大文字小文字区別なしで検索って変なことが起きても仕方がないのでは。
      1. だからって SEGV することはないだろ。
  4. SEGV している部分には "\x8f\xaa\xbc" という文字列があった。これは EUC-JP-MS で Ģ (LATIN CAPITAL LETTER G WITH CEDILLA)。JIS X 0212 のアルファベットでラトビア語の文字らしい。
    1. 環境変数 LANG に指定しているのは ja_JP.eucJP なのに、EUC-JP-MS で検索されているのはいいのか?
  5. 対応する小文字の ģ (LATIN CAPITAL LETTER G WITH CEDILLA) は JIS X 0212 に定義されていないっぽい。JIS X 0212コード表(1)02-31区 - CyberLibrarian の ģ が置かれそうな 11区28点(EUC で 8FABBC) が空欄。
    1. glibc の charmaps/EUC-JP-MS にも 8faabc はある8fabbc はない
    2. よく見たら、EUC-JP も同様に 8faabc はあるけど 8fabbc はないじゃないですか。
  6. GNU grep は -i を付けたとき、小文字に変換してから検索するようで、マルチバイトを一旦 wchar に変換したあと小文字に変換し、マルチバイトに戻しているっぽい
  7. しかし、wcrtomb でマルチバイトに戻した後、返り値(バッファに書き込まれたbyte数)をエラーチェックせずに使用している
  8. "\x8f\xaa\xbc" の場合、EUC-JP では Ģ と解釈され、towlower で 小文字の ģ に変換され、wcrtomb でマルチバイトに戻す時にエラーになり (size_t)-1 が返るが、これを正常なバイト数と思い込んで memset に渡したため SEGV した、と思われる。

ここで突然ですが問題です。誰が悪いのでしょうか。

  1. 未だに EUC-JP を使用している私
  2. バイナリファイルを grep する私
  3. ģ を定義していない JIS X 0212
  4. EUC-JP-MS に ģ がないのに Ģ を ģ に変換してしまう towlower
  5. wcrtomb の返り値チェックをしない grep