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:
parent
926949d64c
commit
3c75a8db35
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue