BufferedReaderのreadLine()
メソッドを使用して、テキスト行をソケットから読み取ります。
読み取る行の長さを制限する明確な方法はありません。
データのソースが(悪意を持ってまたは誤って)改行文字なしで大量のデータを書き込む可能性があることを心配しています。これにより、BufferedReaderが無制限の量のメモリを割り当てます。
それを回避する方法はありますか?または、readLine()
の制限付きバージョンを自分で実装する必要がありますか?
これを行う最も簡単な方法は、独自の境界付きラインリーダーを実装することです。
または、もっと簡単に、 this BoundedBufferedReader
class のコードを再利用します。
実際、標準のメソッドと同じように機能するreadLine()
をコーディングすることは簡単ではありません。 3種類のラインターミネータを正しく処理するには、かなり注意深いコーディングが必要です。上記のリンクのさまざまなアプローチを、BufferedReaderの Sunバージョン および Apache Harmonyバージョン と比較すると興味深いです。
注:制限付きバージョンまたはApacheバージョンのいずれかが100%正しいとは、完全には確信していません。境界バージョンは、基になるストリームがマークとリセットをサポートしていることを前提としていますが、これは常に正しいとは限りません。バッファの最後の文字としてCRが見つかると、Apacheバージョンは1文字先読みしているように見えます。これは、ユーザーが入力した入力を読み取るときにMacOSで壊れます。 Sunバージョンは、次のread...
操作でCRがスキップされる可能性のあるLFを引き起こすフラグを設定することでこれを処理します。つまり、偽の先読みはありません。
別のオプションは、Apache Commonsの BoundedInputStream です。
InputStream bounded = new BoundedInputStream(is, MAX_BYTE_COUNT);
BufferedReader reader = new BufferedReader(new InputStreamReader(bounded));
String line = reader.readLine();
おそらく最も簡単な解決策は、少し異なるアプローチを取ることです。 1つの特定の読み取りを制限することによってDoSを防止しようとする代わりに、読み取られる生データの全体量を制限します。この方法では、割り当てられたメモリが受信データに比例している限り、すべての読み取りとループに特別なコードを使用することを心配する必要はありません。
Reader
、またはおそらくより適切には、デコードされていないStream
または同等のものを測定できます。
文字列の制限は20億文字です。制限を小さくしたい場合は、自分でデータを読み取る必要があります。バッファストリームから、制限または改行文字に達するまで、一度に1つの文字を読み取ることができます。
これを回避する方法はいくつかあります。