Closed hiroki-oogakiuchi closed 1 year ago
issueは作成していません。以下、不具合の再現手順です。 基本多言語面以外の文字(U+10000以降)を入力します。この例では、U+1F604です。
12001(UTF-32BE)にて保存します。
警告が表示されます。この警告が表示されることが1個目の不具合です。無視して[はい]を押下します。
保存直後、画面表示上は、正しく見えます。
バイナリーエディターで見ても、正しく保存されています。(拡張子の違いは無視してください)
一度、サクラエディタを閉じて、先ほど保存したファイルを12001(UTF-32BE)にて開きます。
文字化けしています。符号位置も間違っています。これが2個目の不具合です。
上記手順は、BOM有りの場合でも同様です。また、12000(UTF-32LE)では正しく動作しています。
保存時、 CCodePage::S_UnicodeToUTF32BE→ CCodePage::S_UTF32BEToUnicode→(警告表示)→ CCodePage::S_UnicodeToUTF32BE の順に呼ばれます。 開くとき、 CCodePage::S_UTF32BEToUnicode→ CCodePage::S_UTF32BEToUnicode の順に呼ばれます。 それぞれ、なぜ同じ処理が2回呼ばれるのか、リファクタリングしたいですが、今回はパスします。
CCodePage::S_UnicodeToUTF32BE、839~842行目の変換は正しいので、正しく保存できています。
CCodePage::S_UTF32BEToUnicode、617行目の if( pSrcByte[i] == 0x00 && pSrcByte[i+1] <= 0x10 ) が、U+10000以降の条件になります。
その後、620行目の UINT c = (pSrcByte[i+3] << 16) | (pSrcByte[i+2] << 8) | pSrcByte[i+1]; は、UTF-32の1文字分のchar4個(先頭は0x00)を4byteの変数に入れるのですが、 UTF-32リトルエンディアンの同様箇所、CCodePage::S_UTF32LEToUnicode、530行目 UINT c = (pSrcByte[i+2] << 16) | (pSrcByte[i+1] << 8) | pSrcByte[i]; と比較して、ここではpSrcByteの並びが逆になるだけで、cは同じ値になるはずです。
UTF-32BE 0x00,0x01,0xF6,0x04を、c=0x0001F604
UTF-32LE 0x04,0xF6,0x01,0x00を、c=0x0001F604
よって、620行目を UINT c = (pSrcByte[i+1] << 16) | (pSrcByte[i+2] << 8) | pSrcByte[i+3]; のように修正しました。
不具合再現と同じ手順で、警告無く正しく保存できること、開いたときに文字化けせずに表示できることを確認しました。
UTF-32ビッグエンディアンは滅多に使用されることはありませんが、テキストエディターの基本機能に関わることなので、 関係者の皆さん、よろしくお願いします。
Kudos, SonarCloud Quality Gate passed!
0 Bugs 0 Vulnerabilities 0 Security Hotspots 0 Code Smells
0.0% Coverage 0.0% Duplication
:white_check_mark: Build sakura 1.0.4287 completed (commit https://github.com/sakura-editor/sakura/commit/3d610ad30e by @hiroki-oogakiuchi)
PR対象
カテゴリ
PR の背景
issueは作成していません。以下、不具合の再現手順です。 基本多言語面以外の文字(U+10000以降)を入力します。この例では、U+1F604です。
12001(UTF-32BE)にて保存します。
警告が表示されます。この警告が表示されることが1個目の不具合です。無視して[はい]を押下します。
保存直後、画面表示上は、正しく見えます。
バイナリーエディターで見ても、正しく保存されています。(拡張子の違いは無視してください)
一度、サクラエディタを閉じて、先ほど保存したファイルを12001(UTF-32BE)にて開きます。
文字化けしています。符号位置も間違っています。これが2個目の不具合です。
上記手順は、BOM有りの場合でも同様です。また、12000(UTF-32LE)では正しく動作しています。
不具合箇所の特定
保存時、 CCodePage::S_UnicodeToUTF32BE→ CCodePage::S_UTF32BEToUnicode→(警告表示)→ CCodePage::S_UnicodeToUTF32BE の順に呼ばれます。 開くとき、 CCodePage::S_UTF32BEToUnicode→ CCodePage::S_UTF32BEToUnicode の順に呼ばれます。 それぞれ、なぜ同じ処理が2回呼ばれるのか、リファクタリングしたいですが、今回はパスします。
CCodePage::S_UnicodeToUTF32BE、839~842行目の変換は正しいので、正しく保存できています。
CCodePage::S_UTF32BEToUnicode、617行目の if( pSrcByte[i] == 0x00 && pSrcByte[i+1] <= 0x10 ) が、U+10000以降の条件になります。
その後、620行目の UINT c = (pSrcByte[i+3] << 16) | (pSrcByte[i+2] << 8) | pSrcByte[i+1]; は、UTF-32の1文字分のchar4個(先頭は0x00)を4byteの変数に入れるのですが、 UTF-32リトルエンディアンの同様箇所、CCodePage::S_UTF32LEToUnicode、530行目 UINT c = (pSrcByte[i+2] << 16) | (pSrcByte[i+1] << 8) | pSrcByte[i]; と比較して、ここではpSrcByteの並びが逆になるだけで、cは同じ値になるはずです。
UTF-32BE 0x00,0x01,0xF6,0x04を、c=0x0001F604
UTF-32LE 0x04,0xF6,0x01,0x00を、c=0x0001F604
よって、620行目を UINT c = (pSrcByte[i+1] << 16) | (pSrcByte[i+2] << 8) | pSrcByte[i+3]; のように修正しました。
テスト内容
不具合再現と同じ手順で、警告無く正しく保存できること、開いたときに文字化けせずに表示できることを確認しました。
UTF-32ビッグエンディアンは滅多に使用されることはありませんが、テキストエディターの基本機能に関わることなので、 関係者の皆さん、よろしくお願いします。