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>
This commit is contained in:
Krystian Hebel 2020-10-08 19:19:42 +02:00 committed by Patrick Georgi
parent 926949d64c
commit 3c75a8db35
1 changed files with 33 additions and 39 deletions

View File

@ -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);
}