Open beru opened 6 years ago
CNativeA::AppendStringF/CNativeW::AppendStringF (#303) という関数があります。 現状、内部的にはバッファは 2048 個 固定ですが、この関数を有効活用することで セキュア関数への置き換えを隠蔽できるので対応が楽になります。
個別対応で、やれるときにやる、でなければ放置でもいいのかな、と思っています。
セキュア版関数への置き換えを考える、ということはC言語で書かれているわけで、 「C++で書きなおしたら?」というツッコミが成り立つようにも思えます。 ただ、読みやすさの面で、sstreamよりもsprintfの方が優れている気がしています。
とても重要な課題ですが、他課題が片付くまで塩漬けにしたい所存です。
こことかどうでしょうか?
出力先の文字列長が280文字ですが現在編集中のファイルのパス名を書き込むので。
とはいっても MAX_PATH を超えるようなファイルはそもそも開けないで異常終了するので特に問題はありませんでした。
結構長いパス(D:\123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\aaaaaaaaaaa.txt
)のファイルを作成して編集して保存したら下記のメッセージが表示されました。
---------------------------
sakura
---------------------------
バックアップ先のパス作成中にエラーになりました。
パスが長すぎるか不正な書式です。
バックアップを作成せずに上書き保存してよろしいですか?
---------------------------
はい(Y) いいえ(N)
---------------------------
CViewCommander::Command_COPYTAG
メソッドでは極端に大きい行数と列数のテキストを用意すれば280文字のバッファを超えますが、後続のローカル変数 ptColLine
の領域にはみ出しても特に障害は起きないので結果的に問題無さそうです。LFN対応はまた別の問題ですね。
検討内容はいい雰囲気だと思います。
ただ、いくつか話が混ざってる気がします。
windowsプログラマの常識 MAX_PATH = 260
。
MAX_PATH
は パス文字列の最大を定義する定数です。
たとえば cmd.exe(コマンドプロンプト) はMAX_PATHを超えるパスを扱えません。
最近のWindowsは起動設定のフラグを変更することにより、
この制限を外すことができるようになっているらしいです。
これが LFN(Long File Name)
というやつです。
LFN対応以前の環境で、パス文字列に対してMAX_PATHを超える文字数を確保することは間違っている気がします。組み立てたパスが使えないことが分かっているなら組み立てる意味はないわけで。
では、なぜわざわざMAX_PATHを超える文字数を確保しているか?ですが、これは ANSI → WCHAR の変換で文字数が増える場合があるのを意識して、サクラエディタのコードではメモリを余分に確保しておく慣習があったためと考えられます。
セキュア対応という以前にいろいろ累積の課題はあるように感じています。
たとえば cmd.exe(コマンドプロンプト) はMAX_PATHを超えるパスを扱えません。
OSのバージョンによって違うかもしれませんが、むしろ explorer.exe がリネーム操作が出来なかったりで対応が不十分のようです。
最近のWindowsは起動設定のフラグを変更することにより、 この制限を外すことができるようになっているらしいです。
これについて知らなかったので調べてみました。
詳しい内容が https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file に色々と書いてありました。
WindowsAPIのUnicode版の関数では \\?\
プレフィックスを付加する事で長いファイル名が扱えますが、それ以外にもいろいろ書かれてました。
何やら Windows10, version 1607 からWin32のファイルとディレクトリを扱う関数のMAX_PATH制限を取り除く事が出来るようですが、有効にするには下記の操作を行う必要があるようです。
1) run regedit.exe as administrator 2) locate [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem] 3) change data value [LongPathsEnabled] (DWORD) to "1" 4) close regedit and restart Windows
これも結局レジストリが変更されるみたいです。 gpedit.msc を起動して、
アプリケーション(プロセス)単位でこれも実施しないと有効にならないようです。
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<ws2:longPathAware>true</ws2:longPathAware>
</windowsSettings>
</application>
LFN対応以前の環境で、パス文字列に対してMAX_PATHを超える文字数を確保することは間違っている気がします。組み立てたパスが使えないことが分かっているなら組み立てる意味はないわけで。
NTFS前提ですが、結構前から \\?\
プレフィックスを付ける事で MAX_PATH を超える文字数のファイルを扱えたので、そういうわけではないと思います。
MAX_PATH を超えるファイルの扱いに関しては、別途議論するのがいいと思います。
また、MAX_PATH を超えるファイルの扱いに関してはファイルパスに関係する処理を 扱うクラスを作ってそのクラスの中に隠蔽した方がいいと思います。
NTFS前提ですが、結構前から
\\?\
プレフィックスを付ける事で MAX_PATH を超える文字数のファイルを扱えたので、そういうわけではないと思います。
はい。そうですね。
参考:
http://www2.biglobe.ne.jp/sota/backup.html
では \\?\
プレフィックスを使うことで MAX_PATH を超えるファイルも正しく扱えます。
NTFS前提ですが、結構前から
\\?\
プレフィックスを付ける事で MAX_PATH を超える文字数のファイルを扱えたので、そういうわけではないと思います。
これは抜けてました。
サクラエディタのコードの中にもパスに \\?\
を考慮するユーティリティ関数があります。
ただ、「存在しているだけ」で利用されてはいないと思っています。
「MAX_PATHを越えたら \\?\
を付ける」ならば MAX_PATH を超えるメモリを確保する意味があると思います。そうでないのだから意味はない、で一応理屈は通ってる気がします。
言い方がよろしくないのかも知れませんね。
MAX_PATH
を超えるファイルについては別の issue を設けましょう。
MAX_PATH
を超えるファイルについては別の issue を設けましょう。
セキュアでない関数をセキュアな関数に置き換える https://github.com/sakura-editor/sakura/pull/392#discussion_r214512425