diff options
author | Krystian Hebel <krystian.hebel@3mdeb.com> | 2020-10-08 19:19:42 +0200 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2021-06-11 07:41:41 +0000 |
commit | 3c75a8db35957bd501dfa2443f2e0a74d88c0a3f (patch) | |
tree | 6065363b48b4a4bdc3d3f917bce7c2010000ae75 /src/commonlib/bsd | |
parent | 926949d64c1d8ef49dcc6774dd8535a2cb1fd423 (diff) |
commonlib/lz4_wrapper.c: do not use bitfields
Order of bits in bitfields is implementation-defined. This makes them
non-portable, especially across systems using different endianness.
This change removes bitfields and uses masking and shifting instead.
Signed-off-by: Krystian Hebel <krystian.hebel@3mdeb.com>
Change-Id: Ief7d87ddb25c9baa931f27dbd54a4ca730b6ece7
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55040
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'src/commonlib/bsd')
-rw-r--r-- | src/commonlib/bsd/lz4_wrapper.c | 72 |
1 files changed, 33 insertions, 39 deletions
diff --git a/src/commonlib/bsd/lz4_wrapper.c b/src/commonlib/bsd/lz4_wrapper.c index 73185a5051..73a3571470 100644 --- a/src/commonlib/bsd/lz4_wrapper.c +++ b/src/commonlib/bsd/lz4_wrapper.c @@ -63,39 +63,32 @@ typedef uint64_t U64; #define LZ4F_MAGICNUMBER 0x184D2204 +/* Bit field endianness is implementation-defined. Use masks instead. + * https://stackoverflow.com/a/6044223 */ +#define RESERVED0 0x03 +#define HAS_CONTENT_CHECKSUM 0x04 +#define HAS_CONTENT_SIZE 0x08 +#define HAS_BLOCK_CHECKSUM 0x10 +#define INDEPENDENT_BLOCKS 0x20 +#define VERSION 0xC0 +#define VERSION_SHIFT 6 + +#define RESERVED1_2 0x8F +#define MAX_BLOCK_SIZE 0x70 + struct lz4_frame_header { uint32_t magic; - union { - uint8_t flags; - struct { - uint8_t reserved0 : 2; - uint8_t has_content_checksum : 1; - uint8_t has_content_size : 1; - uint8_t has_block_checksum : 1; - uint8_t independent_blocks : 1; - uint8_t version : 2; - }; - }; - union { - uint8_t block_descriptor; - struct { - uint8_t reserved1 : 4; - uint8_t max_block_size : 3; - uint8_t reserved2 : 1; - }; - }; + uint8_t flags; + uint8_t block_descriptor; /* + uint64_t content_size iff has_content_size is set */ /* + uint8_t header_checksum */ } __packed; +#define BH_SIZE 0x7FFFFFFF +#define NOT_COMPRESSED 0x80000000 + struct lz4_block_header { - union { - uint32_t raw; - struct { - uint32_t size : 31; - uint32_t not_compressed : 1; - }; - }; + uint32_t raw; /* + size bytes of data */ /* + uint32_t block_checksum iff has_block_checksum is set */ } __packed; @@ -114,16 +107,17 @@ size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn) return 0; /* input overrun */ /* We assume there's always only a single, standard frame. */ - if (le32toh(h->magic) != LZ4F_MAGICNUMBER || h->version != 1) + if (le32toh(h->magic) != LZ4F_MAGICNUMBER + || (h->flags & VERSION) != (1 << VERSION_SHIFT)) return 0; /* unknown format */ - if (h->reserved0 || h->reserved1 || h->reserved2) + if ((h->flags & RESERVED0) || (h->block_descriptor & RESERVED1_2)) return 0; /* reserved must be zero */ - if (!h->independent_blocks) + if (!(h->flags & INDEPENDENT_BLOCKS)) return 0; /* we don't support block dependency */ - has_block_checksum = h->has_block_checksum; + has_block_checksum = h->flags & HAS_BLOCK_CHECKSUM; in += sizeof(*h); - if (h->has_content_size) + if (h->flags & HAS_CONTENT_SIZE) in += sizeof(uint64_t); in += sizeof(uint8_t); } @@ -133,28 +127,28 @@ size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn) break; /* input overrun */ struct lz4_block_header b = { - { .raw = le32toh(*(const uint32_t *)in) } + .raw = le32toh(*(const uint32_t *)in) }; in += sizeof(struct lz4_block_header); - if ((size_t)(in - src) + b.size > srcn) + if ((size_t)(in - src) + (b.raw & BH_SIZE) > srcn) break; /* input overrun */ - if (!b.size) { + if (!(b.raw & BH_SIZE)) { out_size = out - dst; break; /* decompression successful */ } - if (b.not_compressed) { - size_t size = MIN((uintptr_t)b.size, (uintptr_t)dst + if (b.raw & NOT_COMPRESSED) { + size_t size = MIN((uintptr_t)(b.raw & BH_SIZE), (uintptr_t)dst + dstn - (uintptr_t)out); memcpy(out, in, size); - if (size < b.size) + if (size < (b.raw & BH_SIZE)) break; /* output overrun */ out += size; } else { /* constant folding essential, do not touch params! */ - int ret = LZ4_decompress_generic(in, out, b.size, + int ret = LZ4_decompress_generic(in, out, (b.raw & BH_SIZE), dst + dstn - out, endOnInputSize, full, 0, noDict, out, NULL, 0); if (ret < 0) @@ -162,7 +156,7 @@ size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn) out += ret; } - in += b.size; + in += (b.raw & BH_SIZE); if (has_block_checksum) in += sizeof(uint32_t); } |