sakura-editor / sakura

SAKURA Editor (Japanese text editor for MS Windows)
https://sakura-editor.github.io/
Other
1.23k stars 162 forks source link

GB単位の大きいデータの「Tab→空白」変換を行うとメモリ確保に失敗した後に応答なしになる #1635

Open beru opened 3 years ago

beru commented 3 years ago

問題内容

GB単位の大きいデータに対してメニューの変換の Tab→空白 を行うと下記のメッセージボックスが表示されます。

---------------------------
sakura(dev Version)(Alpha Version)
---------------------------
CMemory::AllocBuffer(nNewDataLen==-1879048192)
メモリ確保に失敗しました。

---------------------------
OK   キャンセル   
---------------------------

メッセージボックスを閉じるとその後ソフトがハングアップして応答なしになります。

再現手順

1.06 GBのtab文字が大量に含まれたテキストファイルを用意しました。zipだとファイルサイズが大きいので7zで圧縮しました。拡張子を変えて偽装して添付したので tabs.7z にリネーム後に展開して下さい。 tabs.7z.zip

  1. ファイルを開く
  2. 全選択する
  3. メニューの変換の Tab→空白 を選ぶ
  4. メモリ確保に失敗した旨を表示するメッセージボックスが表示されるので閉じる
  5. 応答なしになる

再現頻度

必ず再現する

問題のカテゴリ

環境情報

サクラエディタ   v2.4.2.3686 64bit dev Alpha Version
(GitHash 97b3bfab4720cd498170159d673ca9e1f1051a31)
(GitURL https://github.com/sakura-editor/sakura.git)

      Compile Info: V_A641916 WPR WIN601/I800/C000/N601
      Last Modified: 2021/4/19 00:59:20

https://ci.appveyor.com/project/sakuraeditor/sakura/builds/38760714/job/w3ty0xg9tic7rbba/artifacts

berryzplus commented 3 years ago

サクラエディタが扱えるデータは1行当たりのデータ量が1GBを越えない、総行数が65535行未満のファイルのみです。この制限は x64 ビルドでも同じです。Tab→空白変換を行うとタブ幅設定の数分だけ文字数が増えますが、適切なエラー処理が記述されていないため異常を検出できずにクラッシュします。`

こんなん、他にもいっぱいあるんじゃなかろうか、と。

考えることは主に、 何故こんなことが起きるか? どうしたらこれが直るか? 修正案をマージするにはどうしたらよいか? だと思います。

自分の見立てでは、レビューに参加している人であれば容易に「どうしたら直るか?」までたどり着ける実力を持ってそうです。障害になるのは3つ目で、無責任に「OK」を出せる人が圧倒的に少ないことです。

根治策はおそらく、制限を取っ払うのでなく制限を公開することだと思います。

無論、この問題の原因を「メモリバッファの変換にCNativeWを使っていることだ!」とすると事実上の制限を外せるんですけど、その場合にエラー処理を書かなくてよいかというと違うと思うので、どう対応するにしても「それなりにめんどくさい」です。

beru commented 3 years ago

総行数は65535行以上も扱えると思います。もしどこかの実装のせいできちんと扱えないようになっている場合は手直しした方が良いと思うので教えてください。

実際に何行まで扱えるのかというと、int型で行番号や行indexを扱っていると思うので2の30乗ぐらいまでなら扱えてもおかしくないですが、その前に大体の動作環境で仮想メモリのサイズを超えてメモリ確保に失敗しそうです。行毎にインスタンスを作成するので10億行もあるテキストファイルを開いたら結構メモリを消費するのでDRAMを256GBくらい搭載した環境でないときちんと動作確認出来ないかもしれません。

berryzplus commented 3 years ago

総行数は65535行以上も扱えると思います。

ここ、自分が書き間違っていますね:smiley:

65535行(uint16_tの最大)ではなく、int32_tの最大が正しいです。 Grepに関しては、int64_tの最大までの行数を扱えます。