diff options
| author | Hrutvik Kanabar <hrutvik@google.com> | 2022-10-21 15:34:55 +0000 |
|---|---|---|
| committer | Aleksandr Nogikh <wp32pw@gmail.com> | 2022-11-21 11:06:14 +0100 |
| commit | c49ccaee639efae8b8249272a79e700e2c1954c6 (patch) | |
| tree | 231b5ccb848421e6c3545acb195d575fd693e469 | |
| parent | 5bb7001449cd1dae6cbff2d660374d6d17cbd2c4 (diff) | |
prog: add (de)compression wrappers
Add the file `compression.go`, with entry points for
compressing/decompressing using `zlib`, and encoding/decoding Base64.
Also add roundtrip compress/decompress and encode/decode tests.
| -rw-r--r-- | prog/compression.go | 67 | ||||
| -rw-r--r-- | prog/compression_test.go | 50 |
2 files changed, 117 insertions, 0 deletions
diff --git a/prog/compression.go b/prog/compression.go new file mode 100644 index 000000000..07c3bd02c --- /dev/null +++ b/prog/compression.go @@ -0,0 +1,67 @@ +// Copyright 2022 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "bytes" + "compress/zlib" + "encoding/base64" + "fmt" + "io" +) + +func Compress(rawData []byte) []byte { + var buffer bytes.Buffer + zlibWriter := zlib.NewWriter(&buffer) + + _, err := zlibWriter.Write(rawData) + if err != nil { + panic(fmt.Sprintf("could not compress with zlib: %v", err)) + } + + err = zlibWriter.Close() + if err != nil { + panic(fmt.Sprintf("could not finalize compression with zlib: %v", err)) + } + + return buffer.Bytes() +} + +func Decompress(compressedData []byte) ([]byte, error) { + zlibReader, err := zlib.NewReader(bytes.NewReader(compressedData)) + if err != nil { + return nil, fmt.Errorf("could not initialise zlib: %v", err) + } + + data, err := io.ReadAll(zlibReader) + if err != nil { + return nil, fmt.Errorf("could not read data with zlib: %v", err) + } + + err = zlibReader.Close() + return data, err +} + +func DecodeB64(b64Data []byte) ([]byte, error) { + decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(b64Data)) + rawData, err := io.ReadAll(decoder) + if err != nil { + return nil, fmt.Errorf("could not decode Base64: %v", err) + } + return rawData, nil +} + +func EncodeB64(rawData []byte) []byte { + var buf bytes.Buffer + encoder := base64.NewEncoder(base64.StdEncoding, &buf) + _, err := encoder.Write(rawData) + if err != nil { + panic(fmt.Sprintf("could not encode Base64: %v", err)) + } + err = encoder.Close() + if err != nil { + panic(fmt.Sprintf("could not finalize encoding to Base64: %v", err)) + } + return buf.Bytes() +} diff --git a/prog/compression_test.go b/prog/compression_test.go new file mode 100644 index 000000000..b46f70999 --- /dev/null +++ b/prog/compression_test.go @@ -0,0 +1,50 @@ +// Copyright 2022 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package prog + +import ( + "bytes" + "fmt" + "math/rand" + "testing" +) + +func TestCompress(t *testing.T) { + r := rand.New(randSource(t)) + err := testRoundTrip(r, Compress, Decompress) + if err != nil { + t.Fatalf("compress/decompress %v", err) + } +} + +func TestEncode(t *testing.T) { + r := rand.New(randSource(t)) + err := testRoundTrip(r, EncodeB64, DecodeB64) + if err != nil { + t.Fatalf("encode/decode Base64 %v", err) + } +} + +func testRoundTrip(r *rand.Rand, transform func([]byte) []byte, inverse func([]byte) ([]byte, error)) error { + for i := 0; i < iterCount(); i++ { + randBytes := randomBytes(r) + resultBytes := transform(randBytes) + resultBytes, err := inverse(resultBytes) + if err != nil { + return err + } + if !bytes.Equal(randBytes, resultBytes) { + return fmt.Errorf("roundtrip changes data (original length %d)", len(randBytes)) + } + } + return nil +} + +func randomBytes(r *rand.Rand) []byte { + const maxLen = 1 << 20 // 1 MB. + len := r.Intn(maxLen) + slice := make([]byte, len) + r.Read(slice) + return slice +} |
