[groonga-dev,02541] Re: groonga-normalizer-mysql 1.0.6のgrn_nfkc_char_typeでクラッシュ

Back to archive index

Kouhei Sutou kou****@clear*****
2014年 7月 29日 (火) 17:03:20 JST


須藤です。

In <CAHB5****@mail*****>
  "[groonga-dev,02538] Re: groonga-normalizer-mysql 1.0.6のgrn_nfkc_char_typeでクラッシュ" on Tue, 29 Jul 2014 16:27:52 +0900,
  "yoku ts." <yoku0****@gmail*****> wrote:

> クラッシュするときとしないときがあるというのは、
> 同じ文字列を同じノーマライザーに通していても、
> 途中のnormalized_codeが同じものだとは限らないってことでしょうか。
> (何か腑に落ちない感じはします。。

いや、そうじゃなくて、

  https://github.com/groonga/groonga-normalizer-mysql/blob/master/normalizers/mysql.c#L372

で、normalized_character_lengthがものすごく大きな値になって
いることがあって(どんな値になるかは場合による)、確保してい
るメモリーをはみ出してアクセスすることがあるからです。

> あとぱっと見、
> 
> mysql56> SELECT conv(hex(concat(0xd6, 0xbc, 0xde, 0xac, 0xc9, 0x93, 0x27)),
> 16, 2);
> +--------------------------------------------------------------------+
> | conv(hex(concat(0xd6, 0xbc, 0xde, 0xac, 0xc9, 0x93, 0x27)), 16, 2) |
> +--------------------------------------------------------------------+
> | 11010110101111001101111010101100110010011001001100100111           |
> +--------------------------------------------------------------------+
> 1 row in set (0.00 sec)
> 
> 連続して4ビット以上0になってるところが見当たらなくていいのかなぁ、うーんうーんって感じになったりもします。
>
> ( ´-`).oO(でも落ちてるところがああなので、str[0]= '\0'なんだろうなぁ。うーんうーん。

元の文字列は関係ないですね!
落ちているやつは、正規化後の文字列で起こっています。で、その
正規化後の文字列は

  https://github.com/groonga/groonga-normalizer-mysql/blob/master/normalizers/mysql.c#L318
  normalized = GRN_PLUGIN_MALLOC(ctx, max_normalized_length_in_bytes);

で確保しているんですね。

で、前述の

  current_normalized =
    normalized + normalized_length_in_bytes - normalized_character_length;

で、normalized_character_lengthが大きくなると、normalizedよ
りも前のメモリー領域にアクセスしようとします。ここには何が入っ
ているのかわからないのでクラッシュする可能性は十分あります。

>> ちなみに、同じ文字列
>>   concat(0xd6, 0xbc, 0xde, 0xac, 0xc9, 0x93, 0x27)
>> をMySQL標準のutf8_unicode_ciで正規化したときはどんな文字列に
>> なるかわかりますか?groonga-normalizer-mysqlも同じ挙動にしよ
>> うと思います。
> 
> む、むむぅ。。探してみます。
> (が、クラッシュが頻発しているので、ワークアラウンドっぽいものがあったら
> 探すのを諦めてそちらを適用したい所存。。

であれば、これを試してみてください!

diff --git a/normalizers/mysql.c b/normalizers/mysql.c
index db0d000..f3dab88 100644
--- a/normalizers/mysql.c
+++ b/normalizers/mysql.c
@@ -191,11 +191,14 @@ normalize_character(const char *utf8, int character_length,
     uint32_t normalized_code;
     unsigned int n_bytes;
     normalized_code = normalize_table[page][low_code];
-    if (normalized_code != 0) {
+    if (normalized_code == 0) {
+      *normalized_character_length = 0;
+    } else {
       n_bytes = unichar_to_utf8(normalized_code,
                                 normalized + *normalized_length_in_bytes);
       *normalized_character_length = n_bytes;
       *normalized_length_in_bytes += n_bytes;
+      (*normalized_n_characters)++;
     }
   } else {
     int i;
@@ -204,8 +207,8 @@ normalize_character(const char *utf8, int character_length,
     }
     *normalized_character_length = character_length;
     *normalized_length_in_bytes += character_length;
+    (*normalized_n_characters)++;
   }
-  (*normalized_n_characters)++;
 }
 
 static void


-- 
須藤 功平 <kou****@clear*****>
株式会社クリアコード <http://www.clear-code.com/>

Groongaベースの全文検索システムを総合サポート:
  http://groonga.org/ja/support/
パッチ採用 - プログラミングが楽しい人向けの採用プロセス:
  http://www.clear-code.com/recruitment/
コードリーダー育成支援 - 自然とリーダブルコードを書くチームへ:
  http://www.clear-code.com/services/code-reader/




groonga-dev メーリングリストの案内
Back to archive index