From 0e0f34b8e4f1c60ecaec15c2105982381cc9c3e6 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Tue, 5 Aug 2014 22:03:30 +0300 Subject: liblzma: Add support for lzma_block.ignore_check. Note that this slightly changes how lzma_block_header_decode() has been documented. Earlier it said that the .version is set to the lowest required value, but now it says that the .version field is kept unchanged if possible. In practice this doesn't affect any old code, because before this commit the only possible .version was 0. --- src/liblzma/api/lzma/block.h | 50 ++++++++++++++++++++++++------- src/liblzma/common/block_buffer_encoder.c | 2 +- src/liblzma/common/block_decoder.c | 18 ++++++++--- src/liblzma/common/block_encoder.c | 2 +- src/liblzma/common/block_header_decoder.c | 12 ++++++-- src/liblzma/common/block_header_encoder.c | 2 +- src/liblzma/common/block_util.c | 2 +- 7 files changed, 68 insertions(+), 20 deletions(-) (limited to 'src/liblzma') diff --git a/src/liblzma/api/lzma/block.h b/src/liblzma/api/lzma/block.h index 2e982e1c..7bdcfd7c 100644 --- a/src/liblzma/api/lzma/block.h +++ b/src/liblzma/api/lzma/block.h @@ -31,11 +31,16 @@ typedef struct { /** * \brief Block format version * - * To prevent API and ABI breakages if new features are needed in - * the Block field, a version number is used to indicate which - * fields in this structure are in use. For now, version must always - * be zero. With non-zero version, most Block related functions will - * return LZMA_OPTIONS_ERROR. + * To prevent API and ABI breakages when new features are needed, + * a version number is used to indicate which fields in this + * structure are in use: + * - liblzma >= 5.0.0: version = 0 is supported. + * - liblzma >= 5.1.4beta: Support for version = 1 was added, + * which adds the ignore_check field. + * + * If version is greater than one, most Block related functions + * will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works + * with any version value). * * Read by: * - All functions that take pointer to lzma_block as argument, @@ -233,7 +238,28 @@ typedef struct { lzma_reserved_enum reserved_enum2; lzma_reserved_enum reserved_enum3; lzma_reserved_enum reserved_enum4; - lzma_bool reserved_bool1; + + /** + * \brief A flag to Block decoder to not verify the Check field + * + * This field is supported by liblzma >= 5.1.4beta if .version >= 1. + * + * If this is set to true, the integrity check won't be calculated + * and verified. Unless you know what you are doing, you should + * leave this to false. (A reason to set this to true is when the + * file integrity is verified externally anyway and you want to + * speed up the decompression, which matters mostly when using + * SHA-256 as the integrity check.) + * + * If .version >= 1, read by: + * - lzma_block_decoder() + * - lzma_block_buffer_decode() + * + * Written by (.version is ignored): + * - lzma_block_header_decode() always sets this to false + */ + lzma_bool ignore_check; + lzma_bool reserved_bool2; lzma_bool reserved_bool3; lzma_bool reserved_bool4; @@ -310,10 +336,14 @@ extern LZMA_API(lzma_ret) lzma_block_header_encode( /** * \brief Decode Block Header * - * block->version should be set to the highest value supported by the - * application; currently the only possible version is zero. This function - * will set version to the lowest value that still supports all the features - * required by the Block Header. + * block->version should (usually) be set to the highest value supported + * by the application. If the application sets block->version to a value + * higher than supported by the current liblzma version, this function will + * downgrade block->version to the highest value supported by it. Thus one + * should check the value of block->version after calling this function if + * block->version was set to a non-zero value and the application doesn't + * otherwise know that the liblzma version being used is new enough to + * support the specified block->version. * * The size of the Block Header must have already been decoded with * lzma_block_header_size_decode() macro and stored to block->header_size. diff --git a/src/liblzma/common/block_buffer_encoder.c b/src/liblzma/common/block_buffer_encoder.c index dcd574e9..39e263aa 100644 --- a/src/liblzma/common/block_buffer_encoder.c +++ b/src/liblzma/common/block_buffer_encoder.c @@ -233,7 +233,7 @@ block_buffer_encode(lzma_block *block, const lzma_allocator *allocator, // The contents of the structure may depend on the version so // check the version before validating the contents of *block. - if (block->version != 0) + if (block->version > 1) return LZMA_OPTIONS_ERROR; if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX diff --git a/src/liblzma/common/block_decoder.c b/src/liblzma/common/block_decoder.c index cee6c782..685c3b03 100644 --- a/src/liblzma/common/block_decoder.c +++ b/src/liblzma/common/block_decoder.c @@ -45,6 +45,9 @@ struct lzma_coder_s { /// Check of the uncompressed data lzma_check_state check; + + /// True if the integrity check won't be calculated and verified. + bool ignore_check; }; @@ -97,8 +100,9 @@ block_decode(lzma_coder *coder, const lzma_allocator *allocator, coder->block->uncompressed_size)) return LZMA_DATA_ERROR; - lzma_check_update(&coder->check, coder->block->check, - out + out_start, out_used); + if (!coder->ignore_check) + lzma_check_update(&coder->check, coder->block->check, + out + out_start, out_used); if (ret != LZMA_STREAM_END) return ret; @@ -140,7 +144,9 @@ block_decode(lzma_coder *coder, const lzma_allocator *allocator, if (coder->block->check == LZMA_CHECK_NONE) return LZMA_STREAM_END; - lzma_check_finish(&coder->check, coder->block->check); + if (!coder->ignore_check) + lzma_check_finish(&coder->check, coder->block->check); + coder->sequence = SEQ_CHECK; // Fall through @@ -155,7 +161,8 @@ block_decode(lzma_coder *coder, const lzma_allocator *allocator, // Validate the Check only if we support it. // coder->check.buffer may be uninitialized // when the Check ID is not supported. - if (lzma_check_is_supported(coder->block->check) + if (!coder->ignore_check + && lzma_check_is_supported(coder->block->check) && memcmp(coder->block->raw_check, coder->check.buffer.u8, check_size) != 0) @@ -224,6 +231,9 @@ lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, next->coder->check_pos = 0; lzma_check_init(&next->coder->check, block->check); + next->coder->ignore_check = block->version >= 1 + ? block->ignore_check : false; + // Initialize the filter chain. return lzma_raw_decoder_init(&next->coder->next, allocator, block->filters); diff --git a/src/liblzma/common/block_encoder.c b/src/liblzma/common/block_encoder.c index 15f55f7a..def58641 100644 --- a/src/liblzma/common/block_encoder.c +++ b/src/liblzma/common/block_encoder.c @@ -166,7 +166,7 @@ lzma_block_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, // The contents of the structure may depend on the version so // check the version first. - if (block->version != 0) + if (block->version > 1) return LZMA_OPTIONS_ERROR; // If the Check ID is not supported, we cannot calculate the check and diff --git a/src/liblzma/common/block_header_decoder.c b/src/liblzma/common/block_header_decoder.c index 416642cd..1dd982f6 100644 --- a/src/liblzma/common/block_header_decoder.c +++ b/src/liblzma/common/block_header_decoder.c @@ -46,8 +46,16 @@ lzma_block_header_decode(lzma_block *block, block->filters[i].options = NULL; } - // Always zero for now. - block->version = 0; + // Versions 0 and 1 are supported. If a newer version was specified, + // we need to downgrade it. + if (block->version > 1) + block->version = 1; + + // This isn't a Block Header option, but since the decompressor will + // read it if version >= 1, it's better to initialize it here than + // to expect the caller to do it since in almost all cases this + // should be false. + block->ignore_check = false; // Validate Block Header Size and Check type. The caller must have // already set these, so it is a programming error if this test fails. diff --git a/src/liblzma/common/block_header_encoder.c b/src/liblzma/common/block_header_encoder.c index 707dd0cb..5c5f5424 100644 --- a/src/liblzma/common/block_header_encoder.c +++ b/src/liblzma/common/block_header_encoder.c @@ -17,7 +17,7 @@ extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block) { - if (block->version != 0) + if (block->version > 1) return LZMA_OPTIONS_ERROR; // Block Header Size + Block Flags + CRC32. diff --git a/src/liblzma/common/block_util.c b/src/liblzma/common/block_util.c index 62c93454..00c7fe8d 100644 --- a/src/liblzma/common/block_util.c +++ b/src/liblzma/common/block_util.c @@ -51,7 +51,7 @@ lzma_block_unpadded_size(const lzma_block *block) // NOTE: This function is used for validation too, so it is // essential that these checks are always done even if // Compressed Size is unknown. - if (block == NULL || block->version != 0 + if (block == NULL || block->version > 1 || block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN || block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX || (block->header_size & 3) -- cgit v1.2.3