◀ANSI版開発トップへ
  • 4815 UTF-7 の読み取りミス(?) について
    • 4816 RE: UTF-7 の読み取りミス(?) について
      • 4817 Re2: UTF-7 の読み取りミス(?) について
        • 4825 Re3: UTF-7 の読み取りミス(?) について
          • 4842 Re4: UTF-7 の読み取りミス(?) について
            • 4843 Re5: UTF-7 の読み取りミス(?) について
            • 4851 Re5: UTF-7 の読み取りミス(?) について
      • 4818 Re2: UTF-7 の読み取りミス(?) について
        • 4820 Re3: UTF-7 の読み取りミス(?) について
          • 4821 Re4: UTF-7 の読み取りミス(?) について
          • 4822 Re4: UTF-7 の読み取りミス(?) について
  • [4815] UTF-7 の読み取りミス(?) について ラスティブ 2007年05月12日 18:02

    >>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
    • [4816] RE: UTF-7 の読み取りミス(?) について げんた 2007年05月12日 22:49

      >> 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してみると全然文字になっていないわけでして...
      • [4817] Re2: UTF-7 の読み取りミス(?) について ラスティブ 2007年05月13日 16:02

        ▼ げんたさん
        > ・・・Base 64の結果に+が出現すると
        > UTF-7と誤認識される可能性はかなり高いのではないかと思います.
        > ・・・
        > Set BをDecodeした結果がUTF-16として正当であるところまできちんと判定すれば
        > UTF-7としての誤認識を減らせると思いますが,rastivさんどうでしょう?
        > ・・・

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

        …手届きな方法といえば、恣意的だからという
        (勝手な)理由で封印させていただいてた
        「ありえないフラグ」の復活とか・・・
        そんなものになりそうです。
        • [4825] Re3: UTF-7 の読み取りミス(?) について ラスティブ 2007年05月16日 11:40

          ▼ ラスティブさん
          > ・・・
          > UTF-16 が正当なときとは、
          > UTF-16 が正規なときであると解釈すると、
          > ・・・
          > 分解文字(正規化形式 D 型)と
          > 結合済み文字(正規化形式 C 型)に当てはめたとき、
          > 行き場のない送りなし文字が見つからなかったときのこと・・・
          > となりそうで、 ・・・

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

          http://www.unicode.org/Public/UNIDATA/
          - DerivedNormalizationProps.txt
          • [4842] Re4: UTF-7 の読み取りミス(?) について ラスティブ 2007年05月23日 13:52

            中間報告:

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

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

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

            こうなったら、
            Unicode の予約コードポイントも不正値と見るというのは、
            やりすぎでしょうか・・・。
            • [4843] Re5: UTF-7 の読み取りミス(?) について ラスティブ 2007年05月23日 14:11

              訂正:

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

              誤)
              > 各文字の Combination_Class 値が直前の文字より小さくて
              > 0でなければ整ってないとみる、らしい。
              正)
              > Combination_Class 値が 0 の文字に続く文字の
              > Combination_Class 値が、直前の文字のそれより小さければ、
              > 整ってないとみる、らしい。
            • [4851] Re5: UTF-7 の読み取りミス(?) について ラスティブ 2007年05月28日 19:23

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

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

              ありえないフラグの導入やらで、
              UTF-16 BE/LE の判定条件がよりいっそう厳しくなりまして、
              ワード文書も Unicode と認識されなくなりますけれど、
              バイナリファイルが Unicode に逝てしまうようなことは
              なんとか防げそうです。
      • [4818] Re2: UTF-7 の読み取りミス(?) について じゅうじ 2007年05月14日 23:30

        ▼ げんたさん
        d+hG5ugj9r46NRQqEZMyppcHgFCNCjOO9VCdsCMs6tjoJ6mkE66befz58aqNKRHQ
        > >暫定的にですけれど、自分なりに見つかった問題を報告します。
        > >
        > >charcode.cpp の UTF-7 判別関数に怪しげな部分が…
        > 早速修正して試してみましたが,同じようにUTF-7と認識されてしまいました.

        リリースお疲れ様です。
        このパッチ、少なくとも上記の文字列では大丈夫でした。
        • [4820] Re3: UTF-7 の読み取りミス(?) について げんた 2007年05月15日 00:59

          >このパッチ、少なくとも上記の文字列では大丈夫でした。
          あ,最後に改行がないと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(読み込んだバイト数)となる恐れがある
          と書かれていますが,この『特性』って一体なんでしょうか.
          • [4821] Re4: UTF-7 の読み取りミス(?) について ラスティブ 2007年05月15日 16:18

            ▼ げんたさん
            > ・・・
            > >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


          • [4822] Re4: UTF-7 の読み取りミス(?) について ラスティブ 2007年05月15日 19:12

            補足:

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

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

            つ、つまり要約すると。

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

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