181ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 281ad8388SMartin Matuska // 381ad8388SMartin Matuska /// \file block_decoder.c 481ad8388SMartin Matuska /// \brief Decodes .xz Blocks 581ad8388SMartin Matuska // 681ad8388SMartin Matuska // Author: Lasse Collin 781ad8388SMartin Matuska // 881ad8388SMartin Matuska // This file has been put into the public domain. 981ad8388SMartin Matuska // You can do whatever you want with this file. 1081ad8388SMartin Matuska // 1181ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 1281ad8388SMartin Matuska 1381ad8388SMartin Matuska #include "block_decoder.h" 1481ad8388SMartin Matuska #include "filter_decoder.h" 1581ad8388SMartin Matuska #include "check.h" 1681ad8388SMartin Matuska 1781ad8388SMartin Matuska 1881ad8388SMartin Matuska struct lzma_coder_s { 1981ad8388SMartin Matuska enum { 2081ad8388SMartin Matuska SEQ_CODE, 2181ad8388SMartin Matuska SEQ_PADDING, 2281ad8388SMartin Matuska SEQ_CHECK, 2381ad8388SMartin Matuska } sequence; 2481ad8388SMartin Matuska 2581ad8388SMartin Matuska /// The filters in the chain; initialized with lzma_raw_decoder_init(). 2681ad8388SMartin Matuska lzma_next_coder next; 2781ad8388SMartin Matuska 2881ad8388SMartin Matuska /// Decoding options; we also write Compressed Size and Uncompressed 2981ad8388SMartin Matuska /// Size back to this structure when the decoding has been finished. 3081ad8388SMartin Matuska lzma_block *block; 3181ad8388SMartin Matuska 3281ad8388SMartin Matuska /// Compressed Size calculated while decoding 3381ad8388SMartin Matuska lzma_vli compressed_size; 3481ad8388SMartin Matuska 3581ad8388SMartin Matuska /// Uncompressed Size calculated while decoding 3681ad8388SMartin Matuska lzma_vli uncompressed_size; 3781ad8388SMartin Matuska 3881ad8388SMartin Matuska /// Maximum allowed Compressed Size; this takes into account the 3981ad8388SMartin Matuska /// size of the Block Header and Check fields when Compressed Size 4081ad8388SMartin Matuska /// is unknown. 4181ad8388SMartin Matuska lzma_vli compressed_limit; 4281ad8388SMartin Matuska 4381ad8388SMartin Matuska /// Position when reading the Check field 4481ad8388SMartin Matuska size_t check_pos; 4581ad8388SMartin Matuska 4681ad8388SMartin Matuska /// Check of the uncompressed data 4781ad8388SMartin Matuska lzma_check_state check; 48*53200025SRui Paulo 49*53200025SRui Paulo /// True if the integrity check won't be calculated and verified. 50*53200025SRui Paulo bool ignore_check; 5181ad8388SMartin Matuska }; 5281ad8388SMartin Matuska 5381ad8388SMartin Matuska 5481ad8388SMartin Matuska static inline bool 5581ad8388SMartin Matuska update_size(lzma_vli *size, lzma_vli add, lzma_vli limit) 5681ad8388SMartin Matuska { 5781ad8388SMartin Matuska if (limit > LZMA_VLI_MAX) 5881ad8388SMartin Matuska limit = LZMA_VLI_MAX; 5981ad8388SMartin Matuska 6081ad8388SMartin Matuska if (limit < *size || limit - *size < add) 6181ad8388SMartin Matuska return true; 6281ad8388SMartin Matuska 6381ad8388SMartin Matuska *size += add; 6481ad8388SMartin Matuska 6581ad8388SMartin Matuska return false; 6681ad8388SMartin Matuska } 6781ad8388SMartin Matuska 6881ad8388SMartin Matuska 6981ad8388SMartin Matuska static inline bool 7081ad8388SMartin Matuska is_size_valid(lzma_vli size, lzma_vli reference) 7181ad8388SMartin Matuska { 7281ad8388SMartin Matuska return reference == LZMA_VLI_UNKNOWN || reference == size; 7381ad8388SMartin Matuska } 7481ad8388SMartin Matuska 7581ad8388SMartin Matuska 7681ad8388SMartin Matuska static lzma_ret 77*53200025SRui Paulo block_decode(lzma_coder *coder, const lzma_allocator *allocator, 7881ad8388SMartin Matuska const uint8_t *restrict in, size_t *restrict in_pos, 7981ad8388SMartin Matuska size_t in_size, uint8_t *restrict out, 8081ad8388SMartin Matuska size_t *restrict out_pos, size_t out_size, lzma_action action) 8181ad8388SMartin Matuska { 8281ad8388SMartin Matuska switch (coder->sequence) { 8381ad8388SMartin Matuska case SEQ_CODE: { 8481ad8388SMartin Matuska const size_t in_start = *in_pos; 8581ad8388SMartin Matuska const size_t out_start = *out_pos; 8681ad8388SMartin Matuska 8781ad8388SMartin Matuska const lzma_ret ret = coder->next.code(coder->next.coder, 8881ad8388SMartin Matuska allocator, in, in_pos, in_size, 8981ad8388SMartin Matuska out, out_pos, out_size, action); 9081ad8388SMartin Matuska 9181ad8388SMartin Matuska const size_t in_used = *in_pos - in_start; 9281ad8388SMartin Matuska const size_t out_used = *out_pos - out_start; 9381ad8388SMartin Matuska 9481ad8388SMartin Matuska // NOTE: We compare to compressed_limit here, which prevents 9581ad8388SMartin Matuska // the total size of the Block growing past LZMA_VLI_MAX. 9681ad8388SMartin Matuska if (update_size(&coder->compressed_size, in_used, 9781ad8388SMartin Matuska coder->compressed_limit) 9881ad8388SMartin Matuska || update_size(&coder->uncompressed_size, 9981ad8388SMartin Matuska out_used, 10081ad8388SMartin Matuska coder->block->uncompressed_size)) 10181ad8388SMartin Matuska return LZMA_DATA_ERROR; 10281ad8388SMartin Matuska 103*53200025SRui Paulo if (!coder->ignore_check) 10481ad8388SMartin Matuska lzma_check_update(&coder->check, coder->block->check, 10581ad8388SMartin Matuska out + out_start, out_used); 10681ad8388SMartin Matuska 10781ad8388SMartin Matuska if (ret != LZMA_STREAM_END) 10881ad8388SMartin Matuska return ret; 10981ad8388SMartin Matuska 11081ad8388SMartin Matuska // Compressed and Uncompressed Sizes are now at their final 11181ad8388SMartin Matuska // values. Verify that they match the values given to us. 11281ad8388SMartin Matuska if (!is_size_valid(coder->compressed_size, 11381ad8388SMartin Matuska coder->block->compressed_size) 11481ad8388SMartin Matuska || !is_size_valid(coder->uncompressed_size, 11581ad8388SMartin Matuska coder->block->uncompressed_size)) 11681ad8388SMartin Matuska return LZMA_DATA_ERROR; 11781ad8388SMartin Matuska 11881ad8388SMartin Matuska // Copy the values into coder->block. The caller 11981ad8388SMartin Matuska // may use this information to construct Index. 12081ad8388SMartin Matuska coder->block->compressed_size = coder->compressed_size; 12181ad8388SMartin Matuska coder->block->uncompressed_size = coder->uncompressed_size; 12281ad8388SMartin Matuska 12381ad8388SMartin Matuska coder->sequence = SEQ_PADDING; 12481ad8388SMartin Matuska } 12581ad8388SMartin Matuska 12681ad8388SMartin Matuska // Fall through 12781ad8388SMartin Matuska 12881ad8388SMartin Matuska case SEQ_PADDING: 12981ad8388SMartin Matuska // Compressed Data is padded to a multiple of four bytes. 13081ad8388SMartin Matuska while (coder->compressed_size & 3) { 13181ad8388SMartin Matuska if (*in_pos >= in_size) 13281ad8388SMartin Matuska return LZMA_OK; 13381ad8388SMartin Matuska 13481ad8388SMartin Matuska // We use compressed_size here just get the Padding 13581ad8388SMartin Matuska // right. The actual Compressed Size was stored to 13681ad8388SMartin Matuska // coder->block already, and won't be modified by 13781ad8388SMartin Matuska // us anymore. 13881ad8388SMartin Matuska ++coder->compressed_size; 13981ad8388SMartin Matuska 14081ad8388SMartin Matuska if (in[(*in_pos)++] != 0x00) 14181ad8388SMartin Matuska return LZMA_DATA_ERROR; 14281ad8388SMartin Matuska } 14381ad8388SMartin Matuska 14481ad8388SMartin Matuska if (coder->block->check == LZMA_CHECK_NONE) 14581ad8388SMartin Matuska return LZMA_STREAM_END; 14681ad8388SMartin Matuska 147*53200025SRui Paulo if (!coder->ignore_check) 14881ad8388SMartin Matuska lzma_check_finish(&coder->check, coder->block->check); 149*53200025SRui Paulo 15081ad8388SMartin Matuska coder->sequence = SEQ_CHECK; 15181ad8388SMartin Matuska 15281ad8388SMartin Matuska // Fall through 15381ad8388SMartin Matuska 15481ad8388SMartin Matuska case SEQ_CHECK: { 15581ad8388SMartin Matuska const size_t check_size = lzma_check_size(coder->block->check); 15681ad8388SMartin Matuska lzma_bufcpy(in, in_pos, in_size, coder->block->raw_check, 15781ad8388SMartin Matuska &coder->check_pos, check_size); 15881ad8388SMartin Matuska if (coder->check_pos < check_size) 15981ad8388SMartin Matuska return LZMA_OK; 16081ad8388SMartin Matuska 16181ad8388SMartin Matuska // Validate the Check only if we support it. 16281ad8388SMartin Matuska // coder->check.buffer may be uninitialized 16381ad8388SMartin Matuska // when the Check ID is not supported. 164*53200025SRui Paulo if (!coder->ignore_check 165*53200025SRui Paulo && lzma_check_is_supported(coder->block->check) 16681ad8388SMartin Matuska && memcmp(coder->block->raw_check, 16781ad8388SMartin Matuska coder->check.buffer.u8, 16881ad8388SMartin Matuska check_size) != 0) 16981ad8388SMartin Matuska return LZMA_DATA_ERROR; 17081ad8388SMartin Matuska 17181ad8388SMartin Matuska return LZMA_STREAM_END; 17281ad8388SMartin Matuska } 17381ad8388SMartin Matuska } 17481ad8388SMartin Matuska 17581ad8388SMartin Matuska return LZMA_PROG_ERROR; 17681ad8388SMartin Matuska } 17781ad8388SMartin Matuska 17881ad8388SMartin Matuska 17981ad8388SMartin Matuska static void 180*53200025SRui Paulo block_decoder_end(lzma_coder *coder, const lzma_allocator *allocator) 18181ad8388SMartin Matuska { 18281ad8388SMartin Matuska lzma_next_end(&coder->next, allocator); 18381ad8388SMartin Matuska lzma_free(coder, allocator); 18481ad8388SMartin Matuska return; 18581ad8388SMartin Matuska } 18681ad8388SMartin Matuska 18781ad8388SMartin Matuska 18881ad8388SMartin Matuska extern lzma_ret 189*53200025SRui Paulo lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, 19081ad8388SMartin Matuska lzma_block *block) 19181ad8388SMartin Matuska { 19281ad8388SMartin Matuska lzma_next_coder_init(&lzma_block_decoder_init, next, allocator); 19381ad8388SMartin Matuska 19481ad8388SMartin Matuska // Validate the options. lzma_block_unpadded_size() does that for us 19581ad8388SMartin Matuska // except for Uncompressed Size and filters. Filters are validated 19681ad8388SMartin Matuska // by the raw decoder. 19781ad8388SMartin Matuska if (lzma_block_unpadded_size(block) == 0 19881ad8388SMartin Matuska || !lzma_vli_is_valid(block->uncompressed_size)) 19981ad8388SMartin Matuska return LZMA_PROG_ERROR; 20081ad8388SMartin Matuska 20181ad8388SMartin Matuska // Allocate and initialize *next->coder if needed. 20281ad8388SMartin Matuska if (next->coder == NULL) { 20381ad8388SMartin Matuska next->coder = lzma_alloc(sizeof(lzma_coder), allocator); 20481ad8388SMartin Matuska if (next->coder == NULL) 20581ad8388SMartin Matuska return LZMA_MEM_ERROR; 20681ad8388SMartin Matuska 20781ad8388SMartin Matuska next->code = &block_decode; 20881ad8388SMartin Matuska next->end = &block_decoder_end; 20981ad8388SMartin Matuska next->coder->next = LZMA_NEXT_CODER_INIT; 21081ad8388SMartin Matuska } 21181ad8388SMartin Matuska 21281ad8388SMartin Matuska // Basic initializations 21381ad8388SMartin Matuska next->coder->sequence = SEQ_CODE; 21481ad8388SMartin Matuska next->coder->block = block; 21581ad8388SMartin Matuska next->coder->compressed_size = 0; 21681ad8388SMartin Matuska next->coder->uncompressed_size = 0; 21781ad8388SMartin Matuska 21881ad8388SMartin Matuska // If Compressed Size is not known, we calculate the maximum allowed 21981ad8388SMartin Matuska // value so that encoded size of the Block (including Block Padding) 22081ad8388SMartin Matuska // is still a valid VLI and a multiple of four. 22181ad8388SMartin Matuska next->coder->compressed_limit 22281ad8388SMartin Matuska = block->compressed_size == LZMA_VLI_UNKNOWN 22381ad8388SMartin Matuska ? (LZMA_VLI_MAX & ~LZMA_VLI_C(3)) 22481ad8388SMartin Matuska - block->header_size 22581ad8388SMartin Matuska - lzma_check_size(block->check) 22681ad8388SMartin Matuska : block->compressed_size; 22781ad8388SMartin Matuska 22881ad8388SMartin Matuska // Initialize the check. It's caller's problem if the Check ID is not 22981ad8388SMartin Matuska // supported, and the Block decoder cannot verify the Check field. 23081ad8388SMartin Matuska // Caller can test lzma_check_is_supported(block->check). 23181ad8388SMartin Matuska next->coder->check_pos = 0; 23281ad8388SMartin Matuska lzma_check_init(&next->coder->check, block->check); 23381ad8388SMartin Matuska 234*53200025SRui Paulo next->coder->ignore_check = block->version >= 1 235*53200025SRui Paulo ? block->ignore_check : false; 236*53200025SRui Paulo 23781ad8388SMartin Matuska // Initialize the filter chain. 23881ad8388SMartin Matuska return lzma_raw_decoder_init(&next->coder->next, allocator, 23981ad8388SMartin Matuska block->filters); 24081ad8388SMartin Matuska } 24181ad8388SMartin Matuska 24281ad8388SMartin Matuska 24381ad8388SMartin Matuska extern LZMA_API(lzma_ret) 24481ad8388SMartin Matuska lzma_block_decoder(lzma_stream *strm, lzma_block *block) 24581ad8388SMartin Matuska { 24681ad8388SMartin Matuska lzma_next_strm_init(lzma_block_decoder_init, strm, block); 24781ad8388SMartin Matuska 24881ad8388SMartin Matuska strm->internal->supported_actions[LZMA_RUN] = true; 24981ad8388SMartin Matuska strm->internal->supported_actions[LZMA_FINISH] = true; 25081ad8388SMartin Matuska 25181ad8388SMartin Matuska return LZMA_OK; 25281ad8388SMartin Matuska } 253