Skip to content

Commit

Permalink
fix: Handle lack of CRC digests (#143)
Browse files Browse the repository at this point in the history
* test: Add test case for lack of CRC digests

* fix: Handle lack of CRC digests

Also handle optional booleans correctly.
  • Loading branch information
bodgit authored Dec 12, 2023
1 parent 4a1b176 commit 4ead944
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 35 deletions.
10 changes: 10 additions & 0 deletions reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ func readArchive(t *testing.T, r *sevenzip.ReadCloser) {

rc.Close()

if f.UncompressedSize > 0 && f.CRC32 == 0 {
t.Log("archive member", f.Name, "has no CRC")

continue
}

if !util.CRC32Equal(h.Sum(nil), f.CRC32) {
t.Fatal(errors.New("CRC doesn't match"))
}
Expand Down Expand Up @@ -142,6 +148,10 @@ func TestOpenReader(t *testing.T) {
name: "issue 87",
file: "issue87.7z",
},
{
name: "issue 112",
file: "file_and_empty.7z",
},
{
name: "issue 113",
file: "COMPRESS-492.7z",
Expand Down
19 changes: 9 additions & 10 deletions struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ type packInfo struct {
streams uint64
size []uint64
digest []uint32
defined []bool
}

type coder struct {
Expand Down Expand Up @@ -174,16 +173,14 @@ func (f *folder) unpackSize() uint64 {
}

type unpackInfo struct {
folder []*folder
digest []uint32
defined []bool
folder []*folder
digest []uint32
}

type subStreamsInfo struct {
streams []uint64
size []uint64
digest []uint32
defined []bool
}

type streamsInfo struct {
Expand All @@ -205,13 +202,15 @@ func (si *streamsInfo) FileFolderAndSize(file int) (int, uint64) {

var (
folder int
streams uint64
streams uint64 = 1
)

for folder, streams = range si.subStreamsInfo.streams {
total += streams
if uint64(file) < total {
break
if si.subStreamsInfo != nil {
for folder, streams = range si.subStreamsInfo.streams {
total += streams
if uint64(file) < total {
break
}
}
}

Expand Down
Binary file added testdata/file_and_empty.7z
Binary file not shown.
61 changes: 36 additions & 25 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,24 +132,23 @@ func readSizes(r io.ByteReader, count uint64) ([]uint64, error) {
return sizes, nil
}

func readCRC(r util.Reader, count uint64) ([]uint32, []bool, error) {
func readCRC(r util.Reader, count uint64) ([]uint32, error) {
defined, err := readOptionalBool(r, count)
if err != nil {
return nil, nil, err
return nil, err
}

crcs := make([]uint32, count)

for i := uint64(0); i < count; i++ {
var crc uint32
if err := binary.Read(r, binary.LittleEndian, &crc); err != nil {
return nil, nil, fmt.Errorf("readCRC: Read error: %w", err)
for i := range defined {
if defined[i] {
if err := binary.Read(r, binary.LittleEndian, &crcs[i]); err != nil {
return nil, fmt.Errorf("readCRC: Read error: %w", err)
}
}

crcs[i] = crc
}

return crcs, defined, nil
return crcs, nil
}

//nolint:cyclop
Expand Down Expand Up @@ -185,7 +184,7 @@ func readPackInfo(r util.Reader) (*packInfo, error) {
}

if id == idCRC {
if p.digest, p.defined, err = readCRC(r, p.streams); err != nil {
if p.digest, err = readCRC(r, p.streams); err != nil {
return nil, err
}

Expand Down Expand Up @@ -385,7 +384,7 @@ func readUnpackInfo(r util.Reader) (*unpackInfo, error) {
}

if id == idCRC {
if u.digest, u.defined, err = readCRC(r, folders); err != nil {
if u.digest, err = readCRC(r, folders); err != nil {
return nil, err
}

Expand Down Expand Up @@ -462,7 +461,7 @@ func readSubStreamsInfo(r util.Reader, folder []*folder) (*subStreamsInfo, error
}

if id == idCRC {
if s.digest, s.defined, err = readCRC(r, files); err != nil {
if s.digest, err = readCRC(r, files); err != nil {
return nil, err
}

Expand Down Expand Up @@ -533,7 +532,7 @@ func readStreamsInfo(r util.Reader) (*streamsInfo, error) {
}

func readTimes(r util.Reader, count uint64) ([]time.Time, error) {
_, err := readOptionalBool(r, count)
defined, err := readOptionalBool(r, count)
if err != nil {
return nil, err
}
Expand All @@ -555,15 +554,17 @@ func readTimes(r util.Reader, count uint64) ([]time.Time, error) {
return nil, errors.New("sevenzip: TODO readTimes external") //nolint:goerr113
}

times := make([]time.Time, 0, count)
times := make([]time.Time, count)

for i := uint64(0); i < count; i++ {
var ft windows.Filetime
if err := binary.Read(r, binary.LittleEndian, &ft); err != nil {
return nil, fmt.Errorf("readTimes: Read error: %w", err)
}
for i := range defined {
if defined[i] {
var ft windows.Filetime
if err := binary.Read(r, binary.LittleEndian, &ft); err != nil {
return nil, fmt.Errorf("readTimes: Read error: %w", err)
}

times = append(times, time.Unix(0, ft.Nanoseconds()).UTC())
times[i] = time.Unix(0, ft.Nanoseconds()).UTC()
}
}

return times, nil
Expand Down Expand Up @@ -625,7 +626,7 @@ func readNames(r util.Reader, count, length uint64) ([]string, error) {
}

func readAttributes(r util.Reader, count uint64) ([]uint32, error) {
_, err := readOptionalBool(r, count)
defined, err := readOptionalBool(r, count)
if err != nil {
return nil, err
}
Expand All @@ -648,9 +649,12 @@ func readAttributes(r util.Reader, count uint64) ([]uint32, error) {
}

attributes := make([]uint32, count)
for i := uint64(0); i < count; i++ {
if err := binary.Read(r, binary.LittleEndian, &attributes[i]); err != nil {
return nil, fmt.Errorf("readAttributes: Read error: %w", err)

for i := range defined {
if defined[i] {
if err := binary.Read(r, binary.LittleEndian, &attributes[i]); err != nil {
return nil, fmt.Errorf("readAttributes: Read error: %w", err)
}
}
}

Expand Down Expand Up @@ -827,14 +831,21 @@ func readHeader(r util.Reader) (*header, error) {
return nil, errUnexpectedID
}

if h.streamsInfo == nil || h.filesInfo == nil {
return h, nil
}

j := 0

for i := range h.filesInfo.file {
if h.filesInfo.file[i].isEmptyStream {
continue
}

h.filesInfo.file[i].CRC32 = h.streamsInfo.subStreamsInfo.digest[j]
if h.streamsInfo.subStreamsInfo != nil {
h.filesInfo.file[i].CRC32 = h.streamsInfo.subStreamsInfo.digest[j]
}

_, h.filesInfo.file[i].UncompressedSize = h.streamsInfo.FileFolderAndSize(j)
j++
}
Expand Down

0 comments on commit 4ead944

Please sign in to comment.