Skip to content

Commit 48aa076

Browse files
authored
fix: check CRC and member size stored in trailer
1 parent 163087a commit 48aa076

8 files changed

Lines changed: 129 additions & 39 deletions

File tree

cmd/glzip/compress.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@ func compress(file string, output *os.File, opt options) (err error) {
2323
}
2424

2525
defer func() {
26-
if e := output.Close(); e != nil {
26+
e := output.Close()
27+
if e != nil {
2728
err = e
2829
}
2930
}()
3031

3132
writerOpt := &lzip.WriterOptions{DictSize: uint32(opt.dictionarySize)}
3233

3334
bufWriter := bufio.NewWriter(output)
35+
3436
defer func() {
35-
if e := bufWriter.Flush(); e != nil {
37+
e := bufWriter.Flush()
38+
if e != nil {
3639
err = e
3740
}
3841
}()
@@ -43,7 +46,8 @@ func compress(file string, output *os.File, opt options) (err error) {
4346
}
4447

4548
defer func() {
46-
if e := writer.Close(); e != nil {
49+
e := writer.Close()
50+
if e != nil {
4751
err = e
4852
}
4953
}()
@@ -54,7 +58,8 @@ func compress(file string, output *os.File, opt options) (err error) {
5458
}
5559

5660
defer func() {
57-
if e := input.Close(); e != nil {
61+
e := input.Close()
62+
if e != nil {
5863
err = e
5964
}
6065
}()
@@ -64,7 +69,8 @@ func compress(file string, output *os.File, opt options) (err error) {
6469
}
6570

6671
if !opt.keep {
67-
if err := os.Remove(file); err != nil {
72+
err := os.Remove(file)
73+
if err != nil {
6874
return err
6975
}
7076
}

cmd/glzip/main.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
func main() {
1414
flag.Parse()
15+
1516
args := flag.Args()
1617

1718
if opt.version {
@@ -32,14 +33,16 @@ func main() {
3233

3334
if !opt.decompress {
3435
for _, file := range args {
35-
if err := compress(file, output, opt); err != nil {
36+
err := compress(file, output, opt)
37+
if err != nil {
3638
fmt.Fprintf(os.Stderr, "glzip: %v\n", err)
3739
os.Exit(1)
3840
}
3941
}
4042
} else {
4143
for _, file := range args {
42-
if err := uncompress(file, output, opt); err != nil {
44+
err := uncompress(file, output, opt)
45+
if err != nil {
4346
fmt.Fprintf(os.Stderr, "glzip: %v\n", err)
4447
os.Exit(1)
4548
}

cmd/glzip/main_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ func copyFile(srcFile, dstFile string) error {
3232
}
3333

3434
defer func() {
35-
if e := src.Close(); e != nil {
35+
e := src.Close()
36+
if e != nil {
3637
err = e
3738
}
3839
}()
@@ -43,7 +44,8 @@ func copyFile(srcFile, dstFile string) error {
4344
}
4445

4546
defer func() {
46-
if e := dst.Close(); e != nil {
47+
e := dst.Close()
48+
if e != nil {
4749
err = e
4850
}
4951
}()
@@ -73,7 +75,8 @@ func TestCLI(t *testing.T) {
7375
}
7476

7577
defer func() {
76-
if err := os.Remove("glzip"); err != nil {
78+
err := os.Remove("glzip")
79+
if err != nil {
7780
t.Fatal(err)
7881
}
7982
}()

cmd/glzip/uncompress.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ func uncompress(file string, output *os.File, opt options) (err error) {
2020
}
2121

2222
defer func() {
23-
if e := input.Close(); e != nil {
23+
e := input.Close()
24+
if e != nil {
2425
err = e
2526
}
2627
}()
@@ -42,7 +43,8 @@ func uncompress(file string, output *os.File, opt options) (err error) {
4243
}
4344

4445
defer func() {
45-
if e := output.Close(); e != nil {
46+
e := output.Close()
47+
if e != nil {
4648
err = e
4749
}
4850
}()
@@ -52,7 +54,8 @@ func uncompress(file string, output *os.File, opt options) (err error) {
5254
}
5355

5456
if !opt.keep {
55-
if err := os.Remove(file); err != nil {
57+
err := os.Remove(file)
58+
if err != nil {
5659
return err
5760
}
5861
}

example_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ func ExampleReader() {
5454
}
5555

5656
defer func() {
57-
if err := file.Close(); err != nil {
57+
err := file.Close()
58+
if err != nil {
5859
log.Fatal(err)
5960
}
6061
}()
@@ -80,13 +81,15 @@ func ExampleWriter() {
8081
const text = "The quick brown fox jumps over the lazy dog."
8182

8283
var buf bytes.Buffer
84+
8385
writer := lzip.NewWriter(&buf)
8486

8587
if _, err := io.WriteString(writer, text); err != nil {
8688
log.Fatal(err)
8789
}
8890

89-
if err := writer.Close(); err != nil {
91+
err := writer.Close()
92+
if err != nil {
9093
log.Fatal(err)
9194
}
9295

reader.go

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ func NewReader(r io.Reader) (*Reader, error) {
6060
}
6161

6262
var lzmaHeader [lzma.HeaderLen]byte
63+
6364
lzmaHeader[0] = lzma.Properties{LC: 3, LP: 0, PB: 2}.Code()
6465
binary.LittleEndian.PutUint32(lzmaHeader[1:5], dictSize)
6566
copy(lzmaHeader[5:], rb[len(rb)-16:len(rb)-8])
@@ -85,39 +86,44 @@ func NewReader(r io.Reader) (*Reader, error) {
8586

8687
// Read reads uncompressed data from the stream.
8788
func (z *Reader) Read(p []byte) (n int, err error) {
88-
for n == 0 {
89+
for {
8990
n, err = z.decompressor.Read(p)
90-
if err != nil {
91-
return n, err
92-
}
9391

94-
z.crc = crc32.Update(z.crc, crc32.IEEETable, p[:n])
95-
z.dataSize += uint64(n)
92+
if n > 0 {
93+
z.crc = crc32.Update(z.crc, crc32.IEEETable, p[:n])
94+
z.dataSize += uint64(n)
9695

97-
if !errors.Is(err, io.EOF) {
98-
return n, err
96+
return n, nil
9997
}
10098

101-
var trailer [trailerSize]byte
102-
if _, err := io.ReadFull(z.r, trailer[:]); err != nil {
103-
return n, err
99+
if err == nil {
100+
continue
104101
}
105102

106-
crc := binary.LittleEndian.Uint32(trailer[:4])
107-
if crc != z.crc {
108-
return n, &InvalidCRCError{crc}
109-
}
103+
if errors.Is(err, io.EOF) {
104+
var trailer [trailerSize]byte
105+
if _, err := io.ReadFull(z.r, trailer[:]); err != nil {
106+
return n, err
107+
}
110108

111-
dataSize := binary.LittleEndian.Uint64(trailer[4:12])
112-
if dataSize != z.dataSize {
113-
return n, &InvalidDataSizeError{dataSize}
114-
}
109+
crc := binary.LittleEndian.Uint32(trailer[:4])
110+
if crc != z.crc {
111+
return n, &InvalidCRCError{crc}
112+
}
115113

116-
memberSize := binary.LittleEndian.Uint64(trailer[12:])
117-
if memberSize != z.memberSize {
118-
return n, &InvalidMemberSizeError{memberSize}
114+
dataSize := binary.LittleEndian.Uint64(trailer[4:12])
115+
if dataSize != z.dataSize {
116+
return n, &InvalidDataSizeError{dataSize}
117+
}
118+
119+
memberSize := binary.LittleEndian.Uint64(trailer[12:])
120+
if memberSize != z.memberSize {
121+
return n, &InvalidMemberSizeError{memberSize}
122+
}
123+
124+
return n, io.EOF
119125
}
120-
}
121126

122-
return n, nil
127+
return n, err
128+
}
123129
}

reader_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,67 @@ func TestReaderNonZeroFirstByte(t *testing.T) {
142142
t.Error("unexpected success")
143143
}
144144
}
145+
146+
func TestReadInvalidCRC(t *testing.T) {
147+
t.Parallel()
148+
149+
file, err := os.Open("testdata/fox_bcrc.lz")
150+
if err != nil {
151+
t.Fatal(err)
152+
}
153+
154+
reader, err := lzip.NewReader(file)
155+
if err != nil {
156+
t.Fatal(err)
157+
}
158+
159+
var buf bytes.Buffer
160+
161+
_, err = io.Copy(&buf, reader)
162+
if err == nil {
163+
t.Fatal("unexpected success")
164+
}
165+
166+
var invalidCRCError *lzip.InvalidCRCError
167+
if !errors.As(err, &invalidCRCError) {
168+
t.Fatal("unexpected error type")
169+
}
170+
171+
const expected = 0xEB50_CC6B
172+
173+
if crc := invalidCRCError.CRC; crc != expected {
174+
t.Errorf("expected CRC `%v`, got `%v`", expected, crc)
175+
}
176+
}
177+
178+
func TestReadInvalidMemberSize(t *testing.T) {
179+
t.Parallel()
180+
181+
file, err := os.Open("testdata/fox_mes81.lz")
182+
if err != nil {
183+
t.Fatal(err)
184+
}
185+
186+
reader, err := lzip.NewReader(file)
187+
if err != nil {
188+
t.Fatal(err)
189+
}
190+
191+
var buf bytes.Buffer
192+
193+
_, err = io.Copy(&buf, reader)
194+
if err == nil {
195+
t.Fatal("unexpected success")
196+
}
197+
198+
var invalidMemberSizeError *lzip.InvalidMemberSizeError
199+
if !errors.As(err, &invalidMemberSizeError) {
200+
t.Fatal("unexpected error type")
201+
}
202+
203+
const expected = 81
204+
205+
if memberSize := invalidMemberSizeError.MemberSize; memberSize != expected {
206+
t.Errorf("expected member size `%v`, got `%v`", expected, memberSize)
207+
}
208+
}

writer_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func TestWriter(t *testing.T) {
2525
text := string(data)
2626

2727
var buf bytes.Buffer
28+
2829
writer := lzip.NewWriter(&buf)
2930

3031
n, err := io.WriteString(writer, text)
@@ -160,6 +161,7 @@ func TestVerifyWriterOptions(t *testing.T) {
160161
}
161162

162163
var expected uint32 = (1 << 12) - 1
164+
163165
opt = &lzip.WriterOptions{expected}
164166

165167
err := opt.Verify()

0 commit comments

Comments
 (0)