[▲前のスレッド]

2007/5/12 (土) 18:02:15 ラスティブ  
Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20051027
[4815] UTF-7 の読み取りミス(?) について
>>data:6053
▼ はこねさん
> 以下の文字列のファイルを開こうとすると UTF-7 と
> 判定されて文字化け(?)してしまいます。
> ・・・(中略)・・・
> d+hG5ugj9r46NRQqEZMyppcHgFCNCjOO9VCdsCMs6tjoJ6mkE66befz58aqNKRHQ
> 
> ちなみに、1.5.10.0 では正常に開けました。

暫定的にですけれど、自分なりに見つかった問題を報告します。

charcode.cpp の UTF-7 判別関数に怪しげな部分が…

修正範囲)
charcode.cpp リビジョン 1081 の 342 行から 352 行のところ:

342:		nret = CheckUtf7SetBPart( base_ptr, end_ptr-base_ptr, ptr );
343:		// ここで, [特有バイト数] := [実際に調査されたデータ長] - [不正バイト数]
344:		num_of_base64_encoded_bytes += (ptr-base_ptr) - nret;
345:
346:		// ptr == end_ptr が成り立つ場合, CheckUtf7SetBPart() 関数の特性により,
347:		// 単純に不正バイト数 := ptr-base_ptr(読み込んだバイト数)となる恐れがあるので,
348:		// 条件 ptr == end_ptr が成り立つときはループ脱出.
349:		if( end_ptr <= ptr ){
350:			break;
351:		}
352:		nlostbytes += nret;

修正方法)
上から順に
		nret = CheckUtf7SetBPart( base_ptr, end_ptr-base_ptr, ptr );
消す		// ここで, [特有バイト数] := [実際に調査されたデータ長] - [不正バイト数]
消す		num_of_base64_encoded_bytes += (ptr-base_ptr) - nret;
消す
消す		// ptr == end_ptr が成り立つ場合, CheckUtf7SetBPart() 関数の特性により,
消す		// 単純に不正バイト数 := ptr-base_ptr(読み込んだバイト数)となる恐れがあるので,
消す		// 条件 ptr == end_ptr が成り立つときはループ脱出.
消す		if( end_ptr <= ptr ){
消す			break;
消す		}
書足す		// ptr == end_ptr が成り立つ場合, CheckUtf7SetBPart() 関数の特性により,
書足す		// 単純に不正バイト数 := ptr-base_ptr(読み込んだバイト数)となる恐れがあるので,
書足す		// 条件 ptr == end_ptr が成り立つときはループ脱出.
書足す		if( end_ptr <= ptr ){
書足す			break;
書足す		}
書足す		// ここで, [特有バイト数] := [実際に調査されたデータ長] - [不正バイト数]
書足す		num_of_base64_encoded_bytes += (ptr-base_ptr) - nret;
		nlostbytes += nret;

ちゃんとしたパッチが出せなくてすみません。

# 忘れまいと
# 自分でコメントを入れたそばから・・・ あぁあぁ orz

2007/5/12 (土) 22:49:43 げんた  
INCM1.23c
[4816] RE: UTF-7 の読み取りミス(?) について
>> d+hG5ugj9r46NRQqEZMyppcHgFCNCjOO9VCdsCMs
6tjoJ6mkE66befz58aqNKRHQ
>暫定的にですけれど、自分なりに見つかった問題を報告します。
>
>charcode.cpp の UTF-7 判別関数に怪しげな部分が…

早速修正して試してみましたが,同じようにUTF-7と認識されてしまいました.
ASCIIのみの文字列ですのでUTF-7以外の文字コードのスコアはいずれも0.
UTF-7が1ポイントでも取ればUTF-7になってしまうのでは?

たぶん元の文字列はBase 64の一部ですよね?ちがうかな?
Base64にエンコードされた文字列の一部として+が出現することがあり,UTF-7自体もB partがBase64 Encodeになっているので,Base 64の結果に+が出現するとUTF-7と誤認識される可能性はかなり高いのではないかと思います.

charcode.cppではUTF-7の判定としてSet D, Set Bのチェックしか行っていませんが,Set BをDecodeした結果がUTF-16として正当であるところまできちんと判定すればUTF-7としての誤認識を減らせると思いますが,rastivさんどうでしょう?

上のパターンでも+以降の部分がUTF-7特有と判断されていますが,decodeしてみると全然文字になっていないわけでして...

2007/5/13 (日) 16:02:42 ラスティブ  
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
[4817] Re2: UTF-7 の読み取りミス(?) について
▼ げんたさん
> ・・・Base 64の結果に+が出現すると
> UTF-7と誤認識される可能性はかなり高いのではないかと思います.
> ・・・
> Set BをDecodeした結果がUTF-16として正当であるところまできちんと判定すれば
> UTF-7としての誤認識を減らせると思いますが,rastivさんどうでしょう?
> ・・・


UTF-16 が正当なときとは、
UTF-16 が正規なときであると解釈すると、
未定義領域 0xFFFE と0xFFFF が使われていなくて、
分解文字(正規化形式 D 型)と
結合済み文字(正規化形式 C 型)に当てはめたとき、
行き場のない送りなし文字が見つからなかったときのこと・・・
となりそうで、話がでかくなるのですよね(^^;
# だから外部ライブラリに依頼すぅわ グシャ

…手届きな方法といえば、恣意的だからという
(勝手な)理由で封印させていただいてた
「ありえないフラグ」の復活とか・・・
そんなものになりそうです。

2007/5/16 (水) 11:40:32 ラスティブ  
Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20051027
[4825] Re3: UTF-7 の読み取りミス(?) について
▼ ラスティブさん
> ・・・
> UTF-16 が正当なときとは、
> UTF-16 が正規なときであると解釈すると、
> ・・・
> 分解文字(正規化形式 D 型)と
> 結合済み文字(正規化形式 C 型)に当てはめたとき、
> 行き場のない送りなし文字が見つからなかったときのこと・・・
> となりそうで、  ・・・


ウソを言っておりました。m(_ _)m
Unicode.org のデータを使えば
簡易チェックができるみたいなので、
念頭にいれてみます。。。

http://www.unicode.org/Public/UNIDATA/
- DerivedNormalizationProps.txt

2007/5/23 (水) 13:52:57 ラスティブ  
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
[4842] Re4: UTF-7 の読み取りミス(?) について
中間報告:

Thebe という便利なエディタを使わせてもらって…
目で確認しただけですけれど、例のデータは、

* UTF-16 フォーマットのチェック
 サロゲートペアが正常に組み合わさっているかどうか
* 組み合わせ文字の配列がおかしい
 各文字の Combination_Class 値が直前の文字より小さくて
 0でなければ整ってないとみる、らしい。
 Combination_Class 値が1以上のものは 418 文字でした。
* NFC に絶対出てこない 1115 文字の禁止
 DerivedNormalizationProps.txt で NFC_Quick_Check=No で
 指定されてる文字を検査。

この3つの検査だけではひっかかりませんでした orz.

こうなったら、
Unicode の予約コードポイントも不正値と見るというのは、
やりすぎでしょうか・・・。

2007/5/23 (水) 14:11:16 ラスティブ  
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
[4843] Re5: UTF-7 の読み取りミス(?) について
訂正:

# 案の定というかなんというか

誤)
> 各文字の Combination_Class 値が直前の文字より小さくて
> 0でなければ整ってないとみる、らしい。

正)
> Combination_Class 値が 0 の文字に続く文字の
> Combination_Class 値が、直前の文字のそれより小さければ、
> 整ってないとみる、らしい。


2007/5/28 (月) 19:23:48 ラスティブ  
Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20051027
[4851] Re5: UTF-7 の読み取りミス(?) について
> Unicode の予約コードポイントも不正値と見るというのは、
> やりすぎでしょうか・・・。


数日前のことですが、一応それようのパッチを登録しました。
# Unicode の組み合わせ文字(今のところ 418個)の
# ハッシュによる参照関数が未だできていないのが
# 心残りなのですけれど。。。

ありえないフラグの導入やらで、
UTF-16 BE/LE の判定条件がよりいっそう厳しくなりまして、
ワード文書も Unicode と認識されなくなりますけれど、
バイナリファイルが Unicode に逝てしまうようなことは
なんとか防げそうです。

2007/5/14 (月) 23:30:55 じゅうじ  
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)
[4818] Re2: UTF-7 の読み取りミス(?) について
▼ げんたさん
d+hG5ugj9r46NRQqEZMyppcHgFCNCjOO9VCdsCMs6tjoJ6mkE66befz58aqNKRHQ
> >暫定的にですけれど、自分なりに見つかった問題を報告します。
> > 
> >charcode.cpp の UTF-7 判別関数に怪しげな部分が…
> 早速修正して試してみましたが,同じようにUTF-7と認識されてしまいました.

リリースお疲れ様です。
このパッチ、少なくとも上記の文字列では大丈夫でした。

2007/5/15 (火) 00:59:49 げんた  
INCM1.23c
[4820] Re3: UTF-7 の読み取りミス(?) について
>このパッチ、少なくとも上記の文字列では大丈夫でした。
あ,最後に改行がないとOKですね.改行がある場合は2文字目の+がUTF-7の先頭と判定され,その後62文字アルファベットと数字が続きます.
62 / 8 = 7 あまり 6
あまり6のときは
00xx xxxx  00xx xxxx  00xx xxxx  00xx xxxx  00xx xxxx  00xx 0000 のパターンで
最後の文字の表す値の下位4ビットは0

最後の文字はQで,これの表す値が16.故にUTF-7として正当な値.

というふうに判定されて,
>UTF-7コード検査:特有バイト数=62  ポイント数=62
になります.

>ptr == end_ptr が成り立つ場合, CheckUtf7SetBPart() 関数の特性により,単純に不正バイト数 := ptr-base_ptr(読み込んだバイト数)となる恐れがある
と書かれていますが,この『特性』って一体なんでしょうか.

2007/5/15 (火) 16:18:24 ラスティブ  
Mozilla/5.0 (X11; U; SunOS i86pc; en-US; rv:1.7) Gecko/20051027
[4821] Re4: UTF-7 の読み取りミス(?) について
▼ げんたさん
> ・・・
> >ptr == end_ptr が成り立つ場合, 
> >CheckUtf7SetBPart() 関数の特性により,
> >単純に不正バイト数 := ptr-base_ptr(読み込んだバイト数)
> >となる恐れがある
> と書かれていますが,この『特性』って一体なんでしょうか.

以下の部分を見てみて下さい。

ViewVC の
sakura/trunk/sakura_core/charcode.cpp (リビジョン 1047)
関数 CheckUtf7SetBPart() 内:
267: 		base_ptr = const_cast<uchar_t*>(pS);
268: 		end_ptr = base_ptr + nLen;
269: 		for( ptr = base_ptr; ptr < end_ptr; ++ptr ){
270: 			if( !IsBase64Char( *ptr ) ){
271: 				// UTF-7 Set D 部分の開始を認識.
272: 				break;
273: 			}
274: 		}

これは UTF-7 セットD文字列の開始部分を判断するループです。
判定している部分が2つあります。

1つ目は 270行の条件  !IsBase64Char( *ptr )
2つ目は 269行の条件  ptr < end_ptr

その言う、この関数の特性っていうのは、例えば、
2つ目の条件でセットD文字列だと判断されて、
その後の例の検証ステップに合格するとしたら、
仮に、読み込んだ BASE64 文字列が途中で切れていて、
最後まできちんと調査できないときも、
それにかまわず、不正バイトは見つからなかったと
結果を返してしまうことを表しています。

# この件の本質的な解決にはなってないという落ちです ^^;
# 
# 検証ステップで UTF-7 の BASE64 部分をデコードして得られた
# UTF-16 Be(だったっけ?)の内容のことも考慮すると、
# セットDに含まれる文字がデコード結果の
# UTF-16 Be 文字列に含まれていれば、
# 不正な UTF-7 文字列とすることができます。。。よね?
# けれど、それだけでは普通に作業量が割り増しになるので、
# 調査対象文字列に UTF-7 では使われない値が見つかったら
# UTF-7 の可能性に見切りをつけるようにすれば安くつくかなと、
# 思案中。。。。思案中。
# どうも Unicode の合成文字からは
# 逃げられそうにありません T_T



2007/5/15 (火) 19:12:55 ラスティブ  
Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20051027
[4822] Re4: UTF-7 の読み取りミス(?) について
補足:

> 2つ目の条件でセットD文字列だと判断されて、
> その後の例の検証ステップに合格するとしたら、
> 仮に、読み込んだ BASE64 文字列が途中で切れていて、
> 最後まできちんと調査できないときも、それにかまわず、
> 不正バイトは見つからなかったと結果を返してしまうことを
> 表しています。


逆に、2つ目の条件でセットD文字列だと判断されて、
その後、例の検証ステップに合格しないとしたら、
最後まで調査できてないときでも、それにかまわず、
不正バイト数が見つかったと結果を返してしまいます。

つ、つまり要約すると。

そこに書かれてる特性とは、
最後まで調査できていなくても、
結果を断定しようとする性質のことです (>_<;)

すみません。
実は平々凡々とした内容なのに、
そうでないかのように長々と
講釈を垂れてしまいました orz

[▼次のスレッド]
INCM/CMT
Cyclamen v3.81
[ut:0.010][st:0.000]