ご報告ありがとうございます。 変換できたUTF-16から元のUTF-8の長さを求めるコードに問題があったようで、testブランチで修正しました。 http://git.sourceforge.jp/view?p=ffftp/ffftp.git;a=commit;h=a7acbb14a190ab47c087c1059b1d4742e637ef34
s_kawamoto への返信
ご報告ありがとうございます。 変換できたUTF-16から元のUTF-8の長さを求めるコードに問題があったようで、testブランチで修正しました。 http://git.sourceforge.jp/view?p=ffftp/ffftp.git;a=commit;h=a7acbb14a190ab47c087c1059b1d4742e637ef34
修正ありがとうございます。転送は終わるようになりましたが、境界にひっかかった箇所(以前はクラッシュ)の1文字で???への文字化けが発生しています。こう直せばよいってところまで追いきれていませんが、まずは現象だけの報告です。
修正前は潜在的なバグがあったものの、まず初めの報告の内容が再現できないのですが、修正後も不具合があるとするとお使いの環境に問題があるような気がします。 とりあえずコードページを明示的に指定してみました。 http://git.sourceforge.jp/view?p=ffftp/ffftp.git;a=commit;h=607cd5899fe0ff3692e440cc5fd27e1b21a6cd77
s_kawamoto への返信
修正前は潜在的なバグがあったものの、まず初めの報告の内容が再現できないのですが、修正後も不具合があるとするとお使いの環境に問題があるような気がします。
再現できないとのことですので、1.98eのソース(testブランチではないです)に対してパッチを作成してみました。 ConvUTF8NtoSJIS()のみ修正しています。他のコード変換関数は見ていません。 ホスト側に置いたUTF-8のFFFTP.txtをUTF-8⇒SJIS変換で転送。初回0xd90バイト読み込みで試しています。Windows7で試しているので、WindowsXP以前で悪影響が無いかは未確認ですごめんなさい。
わざわざパッチまで作成していただきありがとうございます。 diffのコメントを読むと原因はWindows Vista以降で不完全な文字がU+FFFDに変換されることのようですが、U+FFFDを特別扱いすると、UTF-8側にU+FFFDが含まれている場合に処理できなくなるので、UTF-8とUTF-16 LE間の変換の処理を自前で実装し、Windows XPのMultiByteToWideChar()とWideCharToMultiByte()をエミュレートしてみました。 http://git.sourceforge.jp/view?p=ffftp/ffftp.git;a=commit;h=2fb62f9065c1e3df9d82414f4055f2d0747ae7ed
s_kawamoto への返信
わざわざパッチまで作成していただきありがとうございます。 diffのコメントを読むと原因はWindows Vista以降で不完全な文字がU+FFFDに変換されることのようですが、U+FFFDを特別扱いすると、UTF-8側にU+FFFDが含まれている場合に処理できなくなるので、UTF-8とUTF-16 LE間の変換の処理を自前で実装し、Windows XPのMultiByteToWideChar()とWideCharToMultiByte()をエミュレートしてみました。 http://git.sourceforge.jp/view?p=ffftp/ffftp.git;a=commit;h=2fb62f9065c1e3df9d82414f4055f2d0747ae7ed
ご指摘の通り、UTF-8にU+FFFD(EF BF BD)が含まれている場合はUTF-16変換時に(FFFD)になっているのでパッチとしてはまずかったです。 また、その後みつけた文字コードまわりのセキュリティの話( http://gihyo.jp/admin/serial/01/charcode )を見ると、もっとよくよく考えてパッチかかないとダメでした。変なパッチ書いてごめんなさい。
一方、修正されたバージョンのRelease版EXEをダウンロードして試してみましたが0xd90バイト読み込んだ後の次の文字が化けてしまいました。
ソースからVC++2008 Express Editionでデバッグビルドして追いかけると、なぜか標準ランタイムのMultiByteToWideChar()とWideCharToMultiByte()が呼ばれていたようなので、それぞれAlternative()付きに書き換えてみましたが、UTF16Length = MultiByteToWideCharAlternative(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length); の戻り値が0になってしまってダメでした。
再現できないような環境依存の問題で、他の方で問題が起きないようでしたら、UTF-8/UTF-16間とはいえ自前変換はセキュリティリスクがあるので以前のバージョンで結構です。
ご迷惑おかけしました。 Windows Vista以降でUTF-8のテキストファイルやファイル名をShift_JISに変換する時に破損するバグを1.98fブランチで修正しましたのでご確認ください。 http://git.sourceforge.jp/view?p=ffftp/ffftp.git;a=commit;h=6e2f6a0d16d98a75a7e1f80470d01b1672e64727
Windows7SP1(x64)で1.98eを使用(他のバージョンはチェックしていません)。ホスト側文字コードUTF-8、ローカル側文字コードSJISでファイルをダウンロードするとクラッシュ(動作を停止しました)する場合があります。
【再現方法】
1. ホスト側コードをUTF-8、ローカル側コードをSJISとする
2. ローカル側のffftp-1.98e-src\doc\jpn\FFFTP.txtをアップロード(UTF-8に変換)
3. ホスト側FFFTP.txtをダウンロードすると(SJISに変換を期待)、「動作を停止しました」ダイアログで終了となります。
デバッガで追いかけた限りだと、ConvUTF8NtoSJIS()の変換中にpUTF16バッファ終端にU+FFFDが現れた場合に文字数カウントがずれてcInfo->StrLenがマイナスになり、次回読み込みで巨大なmalloc()を試みてしまっているようです。バッファ内の条件に依存するようで、history.txtはうまくいきます。