diff options
author | Michael Brown | 2016-03-23 14:41:17 +0100 |
---|---|---|
committer | Michael Brown | 2016-03-24 17:52:26 +0100 |
commit | c4e8c40227ebb11361e066be96ed93927eedfbf4 (patch) | |
tree | ccbcb92feef7ccac12cba9375c09c31cb8fa50e4 /src/util | |
parent | [golan] Fix build error on some versions of gcc (diff) | |
download | ipxe-c4e8c40227ebb11361e066be96ed93927eedfbf4.tar.gz ipxe-c4e8c40227ebb11361e066be96ed93927eedfbf4.tar.xz ipxe-c4e8c40227ebb11361e066be96ed93927eedfbf4.zip |
[prefix] Use CRC32 to verify each block prior to decompression
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/zbin.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/src/util/zbin.c b/src/util/zbin.c index 1862a382..75fba583 100644 --- a/src/util/zbin.c +++ b/src/util/zbin.c @@ -144,6 +144,7 @@ static int read_zinfo_file ( const char *filename, static int alloc_output_file ( size_t max_len, struct output_file *output ) { output->len = 0; + output->hdr_len = 0; output->max_len = ( max_len ); output->buf = malloc ( max_len ); if ( ! output->buf ) { @@ -241,19 +242,41 @@ static void bcj_filter ( void *data, size_t len ) { }; } +#define CRCPOLY 0xedb88320 +#define CRCSEED 0xffffffff + +static uint32_t crc32_le ( uint32_t crc, const void *data, size_t len ) { + const uint8_t *src = data; + uint32_t mult; + unsigned int i; + + while ( len-- ) { + crc ^= *(src++); + for ( i = 0 ; i < 8 ; i++ ) { + mult = ( ( crc & 1 ) ? CRCPOLY : 0 ); + crc = ( ( crc >> 1 ) ^ mult ); + } + } + return crc; +} + static int process_zinfo_pack ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { struct zinfo_pack *pack = &zinfo->pack; size_t offset = pack->offset; size_t len = pack->len; + size_t start_len; size_t packed_len = 0; - size_t remaining = ( output->max_len - output->len ); + size_t remaining; lzma_options_lzma options; const lzma_filter filters[] = { { .id = LZMA_FILTER_LZMA1, .options = &options }, { .id = LZMA_VLI_UNKNOWN } }; + void *packed; + uint32_t *len32; + uint32_t *crc32; if ( ( offset + len ) > input->len ) { fprintf ( stderr, "Input buffer overrun on pack\n" ); @@ -261,6 +284,9 @@ static int process_zinfo_pack ( struct input_file *input, } output->len = align ( output->len, pack->align ); + start_len = output->len; + len32 = ( output->buf + output->len ); + output->len += sizeof ( *len32 ); if ( output->len > output->max_len ) { fprintf ( stderr, "Output buffer overrun on pack\n" ); return -1; @@ -268,28 +294,34 @@ static int process_zinfo_pack ( struct input_file *input, bcj_filter ( ( input->buf + offset ), len ); + packed = ( output->buf + output->len ); + remaining = ( output->max_len - output->len ); lzma_lzma_preset ( &options, LZMA_PRESET ); options.lc = LZMA_LC; options.lp = LZMA_LP; options.pb = LZMA_PB; if ( lzma_raw_buffer_encode ( filters, NULL, ( input->buf + offset ), - len, ( output->buf + output->len ), - &packed_len, remaining ) != LZMA_OK ) { + len, packed, &packed_len, + remaining ) != LZMA_OK ) { fprintf ( stderr, "Compression failure\n" ); return -1; } - - if ( DEBUG ) { - fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n", - offset, ( offset + len ), output->len, - ( output->len + packed_len ) ); - } - output->len += packed_len; + + crc32 = ( output->buf + output->len ); + output->len += sizeof ( *crc32 ); if ( output->len > output->max_len ) { fprintf ( stderr, "Output buffer overrun on pack\n" ); return -1; } + *len32 = ( packed_len + sizeof ( *crc32 ) ); + *crc32 = crc32_le ( CRCSEED, packed, packed_len ); + + if ( DEBUG ) { + fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx) crc %#08x\n", + offset, ( offset + len ), start_len, output->len, + *crc32 ); + } return 0; } |