diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2022-12-17 15:08:10 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2022-12-22 10:11:08 +0100 |
| commit | c692fab1c2ff0de2554c5940f77ac8c168e729b2 (patch) | |
| tree | 4f8e937dc3c11221f510f69abf408727b32067bc | |
| parent | fb1fed72556fcc8fbe60d75a7e70a188f373aa19 (diff) | |
pkg/image: treat empty compressed image as valid image
When we decompress images for mutation or hints,
we always specially check for empty compressed data
(I assume it can apper after minimization).
Treat it as correct compressed and return empty decompressed data.
This removes the need in special handling in users.
| -rw-r--r-- | executor/common_zlib.h | 6 | ||||
| -rw-r--r-- | pkg/csource/generated.go | 14 | ||||
| -rw-r--r-- | pkg/image/compression.go | 10 | ||||
| -rw-r--r-- | pkg/image/compression_nonoptimized.go | 2 | ||||
| -rw-r--r-- | pkg/image/compression_optimized.go | 2 | ||||
| -rw-r--r-- | prog/hints.go | 3 | ||||
| -rw-r--r-- | prog/mutation.go | 3 |
7 files changed, 18 insertions, 22 deletions
diff --git a/executor/common_zlib.h b/executor/common_zlib.h index 5d37cd0e0..fdbd9d4b6 100644 --- a/executor/common_zlib.h +++ b/executor/common_zlib.h @@ -469,10 +469,8 @@ static int puff( static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd) { // Ignore zlib header. - if (sourcelen < ZLIB_HEADER_WIDTH) { - errno = EMSGSIZE; - return -1; - } + if (sourcelen < ZLIB_HEADER_WIDTH) + return 0; source += ZLIB_HEADER_WIDTH; sourcelen -= ZLIB_HEADER_WIDTH; diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go index 754feaa68..8c8fa8d22 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -6640,13 +6640,10 @@ static int puff( static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd) { - if (sourcelen < ZLIB_HEADER_WIDTH) { - errno = EMSGSIZE; - return -1; - } + if (sourcelen < ZLIB_HEADER_WIDTH) + return 0; source += ZLIB_HEADER_WIDTH; sourcelen -= ZLIB_HEADER_WIDTH; - const unsigned long max_destlen = 132 << 20; void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); if (ret == MAP_FAILED) @@ -11783,13 +11780,10 @@ static int puff( static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd) { - if (sourcelen < ZLIB_HEADER_WIDTH) { - errno = EMSGSIZE; - return -1; - } + if (sourcelen < ZLIB_HEADER_WIDTH) + return 0; source += ZLIB_HEADER_WIDTH; sourcelen -= ZLIB_HEADER_WIDTH; - const unsigned long max_destlen = 132 << 20; void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); if (ret == MAP_FAILED) diff --git a/pkg/image/compression.go b/pkg/image/compression.go index 83a479b62..c374ed07b 100644 --- a/pkg/image/compression.go +++ b/pkg/image/compression.go @@ -29,11 +29,21 @@ func Compress(rawData []byte) []byte { return buffer.Bytes() } +func MustDecompress(compressed []byte) (data []byte, dtor func()) { + if len(compressed) == 0 { + return nil, func() {} + } + return mustDecompress(compressed) +} + func DecompressCheck(compressed []byte) error { return decompressWriter(ioutil.Discard, compressed) } func decompressWriter(w io.Writer, compressed []byte) error { + if len(compressed) == 0 { + return nil + } zlibReader, err := zlib.NewReader(bytes.NewReader(compressed)) if err != nil { return fmt.Errorf("could not initialise zlib: %v", err) diff --git a/pkg/image/compression_nonoptimized.go b/pkg/image/compression_nonoptimized.go index 81b26350a..83e17c167 100644 --- a/pkg/image/compression_nonoptimized.go +++ b/pkg/image/compression_nonoptimized.go @@ -13,7 +13,7 @@ import ( var decompressMu sync.Mutex -func MustDecompress(compressed []byte) (data []byte, dtor func()) { +func mustDecompress(compressed []byte) (data []byte, dtor func()) { // Don't decompress more than one image at a time since it can consume lots of memory. // Reconsider when/if we move mutation to the host process. decompressMu.Lock() diff --git a/pkg/image/compression_optimized.go b/pkg/image/compression_optimized.go index bfb9dece2..ac043c3e7 100644 --- a/pkg/image/compression_optimized.go +++ b/pkg/image/compression_optimized.go @@ -29,7 +29,7 @@ var decompressPool = sync.Pool{New: func() interface{} { } }} -func MustDecompress(compressed []byte) (data []byte, dtor func()) { +func mustDecompress(compressed []byte) (data []byte, dtor func()) { // Optimized decompression procedure that is ~2x faster than a naive version // and consumes significantly less memory and generates less garbage. // Images tend to contain lots of 0s, especially the larger images. diff --git a/prog/hints.go b/prog/hints.go index 0055e9005..4821e03b8 100644 --- a/prog/hints.go +++ b/prog/hints.go @@ -159,9 +159,6 @@ func checkDataArg(arg *DataArg, compMap CompMap, exec func()) { func checkCompressedArg(arg *DataArg, compMap CompMap, exec func()) { data0 := arg.Data() - if len(data0) == 0 { - return - } data, dtor := image.MustDecompress(data0) defer dtor() // Images are very large so the generic algorithm for data arguments diff --git a/prog/mutation.go b/prog/mutation.go index 09fdfa69c..07b524fe2 100644 --- a/prog/mutation.go +++ b/prog/mutation.go @@ -385,9 +385,6 @@ func (t *BufferType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls [] } func (r *randGen) mutateImage(compressed []byte) (data []byte, retry bool) { - if len(compressed) == 0 { - return compressed, true - } data, dtor := image.MustDecompress(compressed) defer dtor() if len(data) == 0 { |
