From 3e4227d74c4c4a8e43926df19827d2887d5acb37 Mon Sep 17 00:00:00 2001 From: Sergey Tyapkin Date: Fri, 6 Dec 2024 09:24:41 +0300 Subject: [PATCH] Fix memory allocation in countingReader Currently, countingReader.Seek() uses io.ReadFull() to read data, so memory is allocated for all content of rpm file (and content has no meaning here because only offset of reader must be changed). So while parsing header of big rpm file, a lot of memory allocates. Use reading by small chunks. Signed-off-by: Sergey Tyapkin --- cpio/cpio.go | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/cpio/cpio.go b/cpio/cpio.go index 8e4bba1..a8b1964 100644 --- a/cpio/cpio.go +++ b/cpio/cpio.go @@ -146,12 +146,34 @@ func (cr *countingReader) Seek(offset int64, whence int) (int64, error) { if offset == 0 { return cr.curPos, nil } - b := make([]byte, offset) - n, err := io.ReadFull(cr, b) - if err != nil && err != io.EOF { - return 0, err + totalRead := int64(0) + const chunkSize = int64(1024 * 1024) + buf := make([]byte, chunkSize) + + remaining := offset + for remaining > 0 { + // Define chunk size to read + toRead := chunkSize + if remaining < chunkSize { + toRead = remaining + } + + n, err := cr.Read(buf[:toRead]) + totalRead += int64(n) + remaining -= int64(n) + if err != nil && err != io.EOF { + // If all was read, skip error + if totalRead >= offset { + err = nil + } + return 0, err + } + + if err == io.EOF { + break + } } - return int64(n), nil + return totalRead, nil } func pad(num int) int {