From e242010fd00bdc0b4b506a1123461844fe2ea329 Mon Sep 17 00:00:00 2001 From: Matt Dainty Date: Sat, 26 Apr 2025 00:45:41 +0100 Subject: [PATCH] fix: Handle CRC being in the unpackInfo --- README.md | 2 +- reader.go | 2 +- struct.go | 19 ++++++++++++++----- types.go | 6 +----- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 961991f..c2058fb 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ The worst scenario would likely be to extract the archive in reverse order. ### Detecting the wrong password It's virtually impossible to _reliably_ detect the wrong password versus some other corruption in a password protected archive. -This is partly due to how CBC decryption works; with the wrong password you don't get any sort of decryption error, you just a stream of bytes that aren't the correct ones. +This is partly due to how CBC decryption works; with the wrong password you don't get any sort of decryption error, you just get a stream of bytes that aren't the correct ones. This manifests itself when the file has been compressed _and_ encrypted; during extraction the file is decrypted and then decompressed so with the wrong password the decompression algorithm gets handed a stream which isn't valid so that's the error you see. A `sevenzip.ReadError` error type can be returned for certain operations. diff --git a/reader.go b/reader.go index f75caa4..47c22a0 100644 --- a/reader.go +++ b/reader.go @@ -515,7 +515,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) (err error) { } if !fh.isEmptyStream && !fh.isEmptyFile { - f.folder, _ = header.streamsInfo.FileFolderAndSize(j) + f.folder, _, _ = header.streamsInfo.FileFolderAndSize(j) // Make an exported copy of the folder index f.Stream = f.folder diff --git a/struct.go b/struct.go index 338f0f7..3427a4d 100644 --- a/struct.go +++ b/struct.go @@ -210,28 +210,37 @@ func (si *streamsInfo) Folders() int { return 0 } -func (si *streamsInfo) FileFolderAndSize(file int) (int, uint64) { - total := uint64(0) - +func (si *streamsInfo) FileFolderAndSize(file int) (int, uint64, uint32) { var ( folder int streams uint64 = 1 + crc uint32 ) if si.subStreamsInfo != nil { + total := uint64(0) + for folder, streams = range si.subStreamsInfo.streams { total += streams if uint64(file) < total { //nolint:gosec break } } + + if len(si.subStreamsInfo.digest) > 0 { + crc = si.subStreamsInfo.digest[file] + } } if streams == 1 { - return folder, si.unpackInfo.folder[folder].size[len(si.unpackInfo.folder[folder].coder)-1] + if len(si.unpackInfo.digest) > 0 { + crc = si.unpackInfo.digest[folder] + } + + return folder, si.unpackInfo.folder[folder].size[len(si.unpackInfo.folder[folder].coder)-1], crc } - return folder, si.subStreamsInfo.size[file] + return folder, si.subStreamsInfo.size[file], crc } func (si *streamsInfo) folderOffset(folder int) int64 { diff --git a/types.go b/types.go index c49d1ce..bd470e7 100644 --- a/types.go +++ b/types.go @@ -851,11 +851,7 @@ func readHeader(r util.Reader) (*header, error) { continue } - if h.streamsInfo.subStreamsInfo != nil { - h.filesInfo.file[i].CRC32 = h.streamsInfo.subStreamsInfo.digest[j] - } - - _, h.filesInfo.file[i].UncompressedSize = h.streamsInfo.FileFolderAndSize(j) + _, h.filesInfo.file[i].UncompressedSize, h.filesInfo.file[i].CRC32 = h.streamsInfo.FileFolderAndSize(j) j++ }