Skip to content

Commit 2848168

Browse files
committed
Reader.Reset: recover from errors.
When a Reader encounters an error, its internal state may be corrupted. So Reset needs to be extra thorough, to avoid cascading errors. Based on PR 37 by Sovianum.
1 parent 786ec62 commit 2848168

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

brotli_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,48 @@ func TestEncodeDecode(t *testing.T) {
472472
}
473473
}
474474

475+
func TestErrorReset(t *testing.T) {
476+
compress := func(input []byte) []byte {
477+
var buf bytes.Buffer
478+
writer := new(Writer)
479+
writer.Reset(&buf)
480+
writer.Write(input)
481+
writer.Close()
482+
483+
return buf.Bytes()
484+
}
485+
486+
corruptReader := func(reader *Reader) {
487+
buf := bytes.NewBuffer([]byte("trash"))
488+
reader.Reset(buf)
489+
_, err := io.ReadAll(reader)
490+
if err == nil {
491+
t.Fatalf("successively decompressed invalid input")
492+
}
493+
}
494+
495+
decompress := func(input []byte, reader *Reader) []byte {
496+
buf := bytes.NewBuffer(input)
497+
reader.Reset(buf)
498+
output, err := io.ReadAll(reader)
499+
if err != nil {
500+
t.Fatalf("failed to decompress data %s", err.Error())
501+
}
502+
503+
return output
504+
}
505+
506+
source := []byte("text")
507+
508+
compressed := compress(source)
509+
reader := new(Reader)
510+
corruptReader(reader)
511+
decompressed := decompress(compressed, reader)
512+
if string(source) != string(decompressed) {
513+
t.Fatalf("decompressed data does not match original state")
514+
}
515+
}
516+
475517
// Encode returns content encoded with Brotli.
476518
func Encode(content []byte, options WriterOptions) ([]byte, error) {
477519
var buf bytes.Buffer

reader.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ func NewReader(src io.Reader) *Reader {
3131
// This permits reusing a Reader rather than allocating a new one.
3232
// Error is always nil
3333
func (r *Reader) Reset(src io.Reader) error {
34+
if r.error_code < 0 {
35+
// There was an unrecoverable error, leaving the Reader's state
36+
// undefined. Clear out everything but the buffer.
37+
*r = Reader{buf: r.buf}
38+
}
39+
3440
decoderStateInit(r)
3541
r.src = src
3642
if r.buf == nil {

0 commit comments

Comments
 (0)