diff options
Diffstat (limited to 'src/liblzma/common/block_header_encoder.c')
-rw-r--r-- | src/liblzma/common/block_header_encoder.c | 69 |
1 files changed, 28 insertions, 41 deletions
diff --git a/src/liblzma/common/block_header_encoder.c b/src/liblzma/common/block_header_encoder.c index 9326350b..b9980363 100644 --- a/src/liblzma/common/block_header_encoder.c +++ b/src/liblzma/common/block_header_encoder.c @@ -25,21 +25,20 @@ extern LZMA_API lzma_ret lzma_block_header_size(lzma_block *options) { // Block Header Size + Block Flags + CRC32. - size_t size = 1 + 1 + 4; + uint32_t size = 1 + 1 + 4; // Compressed Size if (options->compressed_size != LZMA_VLI_UNKNOWN) { - if (options->compressed_size > LZMA_VLI_MAX / 4 - 1 - || options->compressed_size == 0 - || (options->compressed_size & 3)) + const uint32_t add = lzma_vli_size(options->compressed_size); + if (add == 0 || options->compressed_size == 0) return LZMA_PROG_ERROR; - size += lzma_vli_size(options->compressed_size / 4 - 1); + size += add; } // Uncompressed Size if (options->uncompressed_size != LZMA_VLI_UNKNOWN) { - const size_t add = lzma_vli_size(options->uncompressed_size); + const uint32_t add = lzma_vli_size(options->uncompressed_size); if (add == 0) return LZMA_PROG_ERROR; @@ -51,10 +50,9 @@ lzma_block_header_size(lzma_block *options) || options->filters[0].id == LZMA_VLI_UNKNOWN) return LZMA_PROG_ERROR; - for (size_t i = 0; options->filters[i].id != LZMA_VLI_UNKNOWN; - ++i) { + for (size_t i = 0; options->filters[i].id != LZMA_VLI_UNKNOWN; ++i) { // Don't allow too many filters. - if (i == 4) + if (i == LZMA_FILTERS_MAX) return LZMA_PROG_ERROR; uint32_t add; @@ -65,12 +63,13 @@ lzma_block_header_size(lzma_block *options) } // Pad to a multiple of four bytes. - options->header_size = (size + 3) & ~(size_t)(3); + options->header_size = (size + 3) & ~UINT32_C(3); - // NOTE: We don't verify that Total Size of the Block stays within - // limits. This is because it is possible that we are called with - // exaggerated values to reserve space for Block Header, and later - // called again with lower, real values. + // NOTE: We don't verify that the encoded size of the Block stays + // within limits. This is because it is possible that we are called + // with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve + // space for Block Header, and later called again with lower, + // real values. return LZMA_OK; } @@ -79,9 +78,9 @@ lzma_block_header_size(lzma_block *options) extern LZMA_API lzma_ret lzma_block_header_encode(const lzma_block *options, uint8_t *out) { - if ((options->header_size & 3) - || options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN - || options->header_size > LZMA_BLOCK_HEADER_SIZE_MAX) + // Valdidate everything but filters. + if (lzma_block_unpadded_size(options) == 0 + || !lzma_vli_is_valid(options->uncompressed_size)) return LZMA_PROG_ERROR; // Indicate the size of the buffer _excluding_ the CRC32 field. @@ -90,32 +89,28 @@ lzma_block_header_encode(const lzma_block *options, uint8_t *out) // Store the Block Header Size. out[0] = out_size / 4; - // We write Block Flags a little later. + // We write Block Flags in pieces. + out[1] = 0x00; size_t out_pos = 2; // Compressed Size if (options->compressed_size != LZMA_VLI_UNKNOWN) { - // Compressed Size must be non-zero, fit into a 63-bit - // integer and be a multiple of four. Also the Total Size - // of the Block must fit into 63-bit integer. - if (options->compressed_size == 0 - || (options->compressed_size & 3) - || options->compressed_size - > LZMA_VLI_MAX - || lzma_block_total_size_get(options) == 0) - return LZMA_PROG_ERROR; - return_if_error(lzma_vli_encode( - options->compressed_size / 4 - 1, NULL, + options->compressed_size, NULL, out, &out_pos, out_size)); + + out[1] |= 0x40; } // Uncompressed Size - if (options->uncompressed_size != LZMA_VLI_UNKNOWN) + if (options->uncompressed_size != LZMA_VLI_UNKNOWN) { return_if_error(lzma_vli_encode( options->uncompressed_size, NULL, out, &out_pos, out_size)); + out[1] |= 0x80; + } + // Filter Flags if (options->filters == NULL || options->filters[0].id == LZMA_VLI_UNKNOWN) @@ -124,24 +119,16 @@ lzma_block_header_encode(const lzma_block *options, uint8_t *out) size_t filter_count = 0; do { // There can be at maximum of four filters. - if (filter_count == 4) + if (filter_count == LZMA_FILTERS_MAX) return LZMA_PROG_ERROR; return_if_error(lzma_filter_flags_encode( options->filters + filter_count, out, &out_pos, out_size)); - } while (options->filters[++filter_count].id - != LZMA_VLI_UNKNOWN); - - // Block Flags - out[1] = filter_count - 1; + } while (options->filters[++filter_count].id != LZMA_VLI_UNKNOWN); - if (options->compressed_size != LZMA_VLI_UNKNOWN) - out[1] |= 0x40; - - if (options->uncompressed_size != LZMA_VLI_UNKNOWN) - out[1] |= 0x80; + out[1] |= filter_count - 1; // Padding memzero(out + out_pos, out_size - out_pos); |