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:
		
				
					committed by
					
						 Patrick Georgi
						Patrick Georgi
					
				
			
			
				
	
			
			
			
						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); | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user