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/