長すぎるパスのファイルを開いくと異常終了する。
また、保存しようとすると、絶対パスが _MAX_PATH
未満となるようにファイル名が切り詰められる。
ANSI版のGetOpenFileName()およびGetSaveFileName()
が _MAX_PATH以上の絶対パスが指定されてもエラーを
返さず、かつバッファ内に'\0'を書かないため、
バッファを突き抜けてしまう。
下記の関数において、GetOpenFileName()または
GetSaveFileName()を呼び出した後バッファの内容を
チェックし'\0'が無ければエラーを表示して指令を
キャンセルする。
unicode版では長いパスを正しく扱えるので、ANSI版
では無理に対応を試みない。
DoModalOpenDlg()
DoModalSaveDlg()
DoModal_GetOpenFileName()
DoModal_GetSaveFileName()
関連議論
dev:5363
data:6689
dev:4733
data:5941
長すぎるファイルパスのオープン・クローズで落ちる
Logged In: YES
user_id=1393397
Originator: NO
・エクスプローラ上のダブルクリック/実行ファイルへのD&D
・CMDからの直接起動
・タグジャンプでの起動
などで、サクラ自体が落ちてしまっていたので、
なすこじさんのパッチで未対処の部分をとりあえず別のパッチとして作りました。
ついでにメニューでMAX_PATH近いファイル名が切れるのを修正しました。
対処方法は、(Open|Save)FileName側と同じ、
警告ダイアログを表示して、ファイル名を空にするだけです。
相対パスを開いた場合で、フルにすると切れるときは
そのまま相対パスになります。(現状維持)
File Added: maxpath_cmd.diff
コマンドライン経由で長すぎるパスで落ちる対策パッチ
エラーとならないことがある不具合を修正、maxpath_cmdの取り込み
Logged In: YES
user_id=1930530
Originator: YES
260バイト目がSJISの1バイト目だとエラーとならないことが
あったのを修正しました。
また、もかさん作成のmaxpath_cmd.diffを取り込みました。
その他メモ:
Windows98では妙なエラーで落ちることがありましたが、
ファイルオープン・セーブで即座に異常終了することは
ありませんでした。
NULLを含まずに260バイト以上の絶対パスは指令が無視
されます。
また、ダイアログで指定した場合、API側にてパスがNULLを
含まずに258バイトに切り詰められてしまいます。
したがってWindows98は本修正の対象外です(修正が適用
されても動作が変化しません)
File Added: FixPathLengthOverflow02.patch
Logged In: YES
user_id=1930530
Originator: YES
編集ウィンドウへのドロップ時の対応を追加しました。
Win98では、'\0'を含めて261バイトちょうどのパスの
場合にサクラエディタが落ちてしまうことがあります。
落ちない場合もあります。
262バイト以上のパスであれば落ちないようです。
WinAPIのGetLongPathName()で落ちているのまでは
分かりましたが、それ以上は調べていないので対処法は
不明です。
File Added: FixPathLengthOverflow03.patch
編集ウィンドウへのドロップに対応
CheckPathLengthOverflowを使ったチェックが4箇所ありますが
GetOpenFileNameRecover/GetOpenFileNameRecover に入れてしまった方が
スマートかなと思います.
DlgOpenFail() のエラー処理を拡張しなくてもCommDlgExtendedError()の結果が0なら
ユーザがキャンセルしたのと同様の扱いになるようなので問題ないように見えます.
マクロでファイル名を扱うケースが抜けているのでは?と思ったのですが,
開く方は一般的にGetLongFileName() で対策されていますね.
反対の保存側を見てみると,CEditDoc::FileWrite() で呼び出される MakeBackUp() での
チェックが行われていないようです.バックアップは元のファイル名より長くなる場合もありますので
注意が必要です.
# ローカルディスクでは長すぎるファイルというのは作れないんですね.
# 長すぎるよとExplorerに怒られます.
# なので動作試験はできていません.
チェック位置の変更とバックアップファイルへの対応の追加
チェックをDoModal...()の関数からGetOpenFileNameRecover()/GetSaveFileNameRecover()
に移動しました。
また、バックアップファイル作成時のファイルパスもチェックするようにしました。
前回は気が付きませんでしたが、上書き確認の後にパス長確認になっています。
なので、フックを使わない場合上書き確認でOKした後パス長でエラーとなります。
フックを使う場合、プロシージャ内で_MAX_PATH未満にパスを切り詰めているので
上書き確認できず、たまたまパス長エラーだけが表示されます。
(切り詰めたパス名と同名ファイルがあると上書き確認される)
セーブダイアログは必ずフックを使用しプロシージャ内でもパス長チェックする
のが理想的と思いますが、今回そこまでは修正していません。
260バイト以上のパス長のファイルは、"C:\a"のような1文字フォルダに長い
ファイル名のファイルを作成しフォルダ名を変更すると作成可能です。
File Added: FixPathLengthOverflow04.patch
バックアップファイルのパス作成時のチェックを強化しました。
File Added: FixPathLengthOverflow05.patch
バックアップファイルのパス作成時のチェックを強化
CEditDoc 1799行目
拡張子置換処理で,bOverflow = true;の後ろにbreak;が抜けてますね.
バックアップパターンに *_*_*_*_*_*_* と入れると
バッファオーバーランします.
そこだけ修正すればcommitしても良いと思います.
breakが抜けていたので追加
抜けていたbreakを追加しrev1474でコミットしました。
File Added: FixPathLengthOverflow06.patch