From 7f260be218b66dc1c5b2d6be2d5c0925aa9a4a0d Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Tue, 25 Jan 2022 01:28:20 -0800 Subject: [PATCH] zstd: improve header decoder (#476) Changes made: * Add Header.HeaderSize to track the actual size of the header. The header is variable length, so providing this information allows the caller to do other low-level tasks, such as determining whether the entirety of a zstandard frame is a single segment block. * Add Header.Skippable{ID,Size} to make the Header type more useful for extracting data from metadata frames (see #459). * Re-arrange fields in Header to better match the order these appear in RFC 8478. --- zstd/decodeheader.go | 84 ++++++++++++++++++---------- zstd/decodeheader_test.go | 2 +- zstd/testdata/headers-want.json.zst | Bin 16592 -> 15493 bytes 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/zstd/decodeheader.go b/zstd/decodeheader.go index 69736e8d4b..5022e71c83 100644 --- a/zstd/decodeheader.go +++ b/zstd/decodeheader.go @@ -5,6 +5,7 @@ package zstd import ( "bytes" + "encoding/binary" "errors" "io" ) @@ -15,18 +16,50 @@ const HeaderMaxSize = 14 + 3 // Header contains information about the first frame and block within that. type Header struct { - // Window Size the window of data to keep while decoding. - // Will only be set if HasFCS is false. - WindowSize uint64 + // SingleSegment specifies whether the data is to be decompressed into a + // single contiguous memory segment. + // It implies that WindowSize is invalid and that FrameContentSize is valid. + SingleSegment bool - // Frame content size. - // Expected size of the entire frame. - FrameContentSize uint64 + // WindowSize is the window of data to keep while decoding. + // Will only be set if SingleSegment is false. + WindowSize uint64 // Dictionary ID. // If 0, no dictionary. DictionaryID uint32 + // HasFCS specifies whether FrameContentSize has a valid value. + HasFCS bool + + // FrameContentSize is the expected uncompressed size of the entire frame. + FrameContentSize uint64 + + // Skippable will be true if the frame is meant to be skipped. + // This implies that FirstBlock.OK is false. + Skippable bool + + // SkippableID is the user-specific ID for the skippable frame. + // Valid values are between 0 to 15, inclusive. + SkippableID int + + // SkippableSize is the length of the user data to skip following + // the header. + SkippableSize uint32 + + // HeaderSize is the raw size of the frame header. + // + // For normal frames, it includes the size of the magic number and + // the size of the header (per section 3.1.1.1). + // It does not include the size for any data blocks (section 3.1.1.2) nor + // the size for the trailing content checksum. + // + // For skippable frames, this counts the size of the magic number + // along with the size of the size field of the payload. + // It does not include the size of the skippable payload itself. + // The total frame size is the HeaderSize plus the SkippableSize. + HeaderSize int + // First block information. FirstBlock struct { // OK will be set if first block could be decoded. @@ -51,17 +84,9 @@ type Header struct { CompressedSize int } - // Skippable will be true if the frame is meant to be skipped. - // No other information will be populated. - Skippable bool - // If set there is a checksum present for the block content. + // The checksum field at the end is always 4 bytes long. HasCheckSum bool - - // If this is true FrameContentSize will have a valid value - HasFCS bool - - SingleSegment bool } // Decode the header from the beginning of the stream. @@ -71,39 +96,46 @@ type Header struct { // If there isn't enough input, io.ErrUnexpectedEOF is returned. // The FirstBlock.OK will indicate if enough information was available to decode the first block header. func (h *Header) Decode(in []byte) error { + *h = Header{} if len(in) < 4 { return io.ErrUnexpectedEOF } + h.HeaderSize += 4 b, in := in[:4], in[4:] if !bytes.Equal(b, frameMagic) { if !bytes.Equal(b[1:4], skippableFrameMagic) || b[0]&0xf0 != 0x50 { return ErrMagicMismatch } - *h = Header{Skippable: true} + if len(in) < 4 { + return io.ErrUnexpectedEOF + } + h.HeaderSize += 4 + h.Skippable = true + h.SkippableID = int(b[0] & 0xf) + h.SkippableSize = binary.LittleEndian.Uint32(in) return nil } + + // Read Window_Descriptor + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#window_descriptor if len(in) < 1 { return io.ErrUnexpectedEOF } - - // Clear output - *h = Header{} fhd, in := in[0], in[1:] + h.HeaderSize++ h.SingleSegment = fhd&(1<<5) != 0 h.HasCheckSum = fhd&(1<<2) != 0 - if fhd&(1<<3) != 0 { return errors.New("reserved bit set on frame header") } - // Read Window_Descriptor - // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#window_descriptor if !h.SingleSegment { if len(in) < 1 { return io.ErrUnexpectedEOF } var wd byte wd, in = in[0], in[1:] + h.HeaderSize++ windowLog := 10 + (wd >> 3) windowBase := uint64(1) << windowLog windowAdd := (windowBase / 8) * uint64(wd&0x7) @@ -120,9 +152,7 @@ func (h *Header) Decode(in []byte) error { return io.ErrUnexpectedEOF } b, in = in[:size], in[size:] - if b == nil { - return io.ErrUnexpectedEOF - } + h.HeaderSize += int(size) switch size { case 1: h.DictionaryID = uint32(b[0]) @@ -152,9 +182,7 @@ func (h *Header) Decode(in []byte) error { return io.ErrUnexpectedEOF } b, in = in[:fcsSize], in[fcsSize:] - if b == nil { - return io.ErrUnexpectedEOF - } + h.HeaderSize += int(fcsSize) switch fcsSize { case 1: h.FrameContentSize = uint64(b[0]) diff --git a/zstd/decodeheader_test.go b/zstd/decodeheader_test.go index 999592b24f..3ff9ead619 100644 --- a/zstd/decodeheader_test.go +++ b/zstd/decodeheader_test.go @@ -82,7 +82,7 @@ func TestHeader_Decode(t *testing.T) { t.Errorf("want error, got result: %v", got) } if want != got { - t.Errorf("want %#v, got %#v", want, got) + t.Errorf("header mismatch:\nwant %#v\ngot %#v", want, got) } }) } diff --git a/zstd/testdata/headers-want.json.zst b/zstd/testdata/headers-want.json.zst index bf66202a656b6b49d7c8254afcc3705af28ffa0c..6c88d320973cf0a493750ac48d89b130e9bb7688 100644 GIT binary patch literal 15493 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 HKDB7C=M97t literal 16592 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 TOu4&L&^8tW0Cxj6j_~)2;n)g=