1219732Sume/////////////////////////////////////////////////////////////////////////////// 2219732Sume// 3219732Sume/// \file block_decoder.c 4219732Sume/// \brief Decodes .xz Blocks 5219732Sume// 6219732Sume// Author: Lasse Collin 7219732Sume// 8219732Sume// This file has been put into the public domain. 9219732Sume// You can do whatever you want with this file. 10219732Sume// 11219732Sume/////////////////////////////////////////////////////////////////////////////// 12219732Sume 13219732Sume#include "block_decoder.h" 14219732Sume#include "filter_decoder.h" 15219732Sume#include "check.h" 16219732Sume 17219732Sume 18219732Sumetypedef struct { 19219732Sume enum { 20219732Sume SEQ_CODE, 21219732Sume SEQ_PADDING, 22219732Sume SEQ_CHECK, 23219732Sume } sequence; 24219732Sume 25219732Sume /// The filters in the chain; initialized with lzma_raw_decoder_init(). 26219732Sume lzma_next_coder next; 27219732Sume 28219732Sume /// Decoding options; we also write Compressed Size and Uncompressed 29219732Sume /// Size back to this structure when the decoding has been finished. 30219732Sume lzma_block *block; 31219732Sume 32219732Sume /// Compressed Size calculated while decoding 33219732Sume lzma_vli compressed_size; 34219732Sume 35219732Sume /// Uncompressed Size calculated while decoding 36219732Sume lzma_vli uncompressed_size; 37219732Sume 38219732Sume /// Maximum allowed Compressed Size; this takes into account the 39219732Sume /// size of the Block Header and Check fields when Compressed Size 40219732Sume /// is unknown. 41219732Sume lzma_vli compressed_limit; 42219732Sume 43219732Sume /// Position when reading the Check field 44219732Sume size_t check_pos; 45219732Sume 46219732Sume /// Check of the uncompressed data 47219732Sume lzma_check_state check; 48219732Sume 49219732Sume /// True if the integrity check won't be calculated and verified. 50219732Sume bool ignore_check; 51219732Sume} lzma_block_coder; 52219732Sume 53219732Sume 54219732Sumestatic inline bool 55219732Sumeupdate_size(lzma_vli *size, lzma_vli add, lzma_vli limit) 56219732Sume{ 57219732Sume if (limit > LZMA_VLI_MAX) 58219732Sume limit = LZMA_VLI_MAX; 59219732Sume 60219732Sume if (limit < *size || limit - *size < add) 61219732Sume return true; 62219732Sume 63219732Sume *size += add; 64219732Sume 65219732Sume return false; 66219732Sume} 67219732Sume 68219732Sume 69219732Sumestatic inline bool 70219732Sumeis_size_valid(lzma_vli size, lzma_vli reference) 71219732Sume{ 72219732Sume return reference == LZMA_VLI_UNKNOWN || reference == size; 73219732Sume} 74219732Sume 75219732Sume 76219732Sumestatic lzma_ret 77219732Sumeblock_decode(void *coder_ptr, const lzma_allocator *allocator, 78219732Sume const uint8_t *restrict in, size_t *restrict in_pos, 79219732Sume size_t in_size, uint8_t *restrict out, 80219732Sume size_t *restrict out_pos, size_t out_size, lzma_action action) 81219732Sume{ 82219732Sume lzma_block_coder *coder = coder_ptr; 83219732Sume 84219732Sume switch (coder->sequence) { 85219732Sume case SEQ_CODE: { 86219732Sume const size_t in_start = *in_pos; 87219732Sume const size_t out_start = *out_pos; 88219732Sume 89219732Sume const lzma_ret ret = coder->next.code(coder->next.coder, 90219732Sume allocator, in, in_pos, in_size, 91219732Sume out, out_pos, out_size, action); 92219732Sume 93219732Sume const size_t in_used = *in_pos - in_start; 94219732Sume const size_t out_used = *out_pos - out_start; 95219732Sume 96219732Sume // NOTE: We compare to compressed_limit here, which prevents 97219732Sume // the total size of the Block growing past LZMA_VLI_MAX. 98219732Sume if (update_size(&coder->compressed_size, in_used, 99219732Sume coder->compressed_limit) 100219732Sume || update_size(&coder->uncompressed_size, 101219732Sume out_used, 102219732Sume coder->block->uncompressed_size)) 103219732Sume return LZMA_DATA_ERROR; 104219732Sume 105219732Sume if (!coder->ignore_check) 106219732Sume lzma_check_update(&coder->check, coder->block->check, 107219732Sume out + out_start, out_used); 108219732Sume 109219732Sume if (ret != LZMA_STREAM_END) 110219732Sume return ret; 111219732Sume 112219732Sume // Compressed and Uncompressed Sizes are now at their final 113219732Sume // values. Verify that they match the values given to us. 114219732Sume if (!is_size_valid(coder->compressed_size, 115219732Sume coder->block->compressed_size) 116219732Sume || !is_size_valid(coder->uncompressed_size, 117219732Sume coder->block->uncompressed_size)) 118219732Sume return LZMA_DATA_ERROR; 119219732Sume 120219732Sume // Copy the values into coder->block. The caller 121219732Sume // may use this information to construct Index. 122219732Sume coder->block->compressed_size = coder->compressed_size; 123219732Sume coder->block->uncompressed_size = coder->uncompressed_size; 124219732Sume 125219732Sume coder->sequence = SEQ_PADDING; 126219732Sume } 127219732Sume 128219732Sume // Fall through 129219732Sume 130219732Sume case SEQ_PADDING: 131219732Sume // Compressed Data is padded to a multiple of four bytes. 132219732Sume while (coder->compressed_size & 3) { 133219732Sume if (*in_pos >= in_size) 134225524Shrs return LZMA_OK; 135219732Sume 136219732Sume // We use compressed_size here just get the Padding 137219732Sume // right. The actual Compressed Size was stored to 138219732Sume // coder->block already, and won't be modified by 139219732Sume // us anymore. 140219732Sume ++coder->compressed_size; 141219732Sume 142219732Sume if (in[(*in_pos)++] != 0x00) 143219732Sume return LZMA_DATA_ERROR; 144225524Shrs } 145219732Sume 146219732Sume if (coder->block->check == LZMA_CHECK_NONE) 147225524Shrs return LZMA_STREAM_END; 148219732Sume 149219732Sume if (!coder->ignore_check) 150219732Sume lzma_check_finish(&coder->check, coder->block->check); 151219732Sume 152219732Sume coder->sequence = SEQ_CHECK; 153219732Sume 154 // Fall through 155 156 case SEQ_CHECK: { 157 const size_t check_size = lzma_check_size(coder->block->check); 158 lzma_bufcpy(in, in_pos, in_size, coder->block->raw_check, 159 &coder->check_pos, check_size); 160 if (coder->check_pos < check_size) 161 return LZMA_OK; 162 163 // Validate the Check only if we support it. 164 // coder->check.buffer may be uninitialized 165 // when the Check ID is not supported. 166 if (!coder->ignore_check 167 && lzma_check_is_supported(coder->block->check) 168 && memcmp(coder->block->raw_check, 169 coder->check.buffer.u8, 170 check_size) != 0) 171 return LZMA_DATA_ERROR; 172 173 return LZMA_STREAM_END; 174 } 175 } 176 177 return LZMA_PROG_ERROR; 178} 179 180 181static void 182block_decoder_end(void *coder_ptr, const lzma_allocator *allocator) 183{ 184 lzma_block_coder *coder = coder_ptr; 185 lzma_next_end(&coder->next, allocator); 186 lzma_free(coder, allocator); 187 return; 188} 189 190 191extern lzma_ret 192lzma_block_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, 193 lzma_block *block) 194{ 195 lzma_next_coder_init(&lzma_block_decoder_init, next, allocator); 196 197 // Validate the options. lzma_block_unpadded_size() does that for us 198 // except for Uncompressed Size and filters. Filters are validated 199 // by the raw decoder. 200 if (lzma_block_unpadded_size(block) == 0 201 || !lzma_vli_is_valid(block->uncompressed_size)) 202 return LZMA_PROG_ERROR; 203 204 // Allocate *next->coder if needed. 205 lzma_block_coder *coder = next->coder; 206 if (coder == NULL) { 207 coder = lzma_alloc(sizeof(lzma_block_coder), allocator); 208 if (coder == NULL) 209 return LZMA_MEM_ERROR; 210 211 next->coder = coder; 212 next->code = &block_decode; 213 next->end = &block_decoder_end; 214 coder->next = LZMA_NEXT_CODER_INIT; 215 } 216 217 // Basic initializations 218 coder->sequence = SEQ_CODE; 219 coder->block = block; 220 coder->compressed_size = 0; 221 coder->uncompressed_size = 0; 222 223 // If Compressed Size is not known, we calculate the maximum allowed 224 // value so that encoded size of the Block (including Block Padding) 225 // is still a valid VLI and a multiple of four. 226 coder->compressed_limit 227 = block->compressed_size == LZMA_VLI_UNKNOWN 228 ? (LZMA_VLI_MAX & ~LZMA_VLI_C(3)) 229 - block->header_size 230 - lzma_check_size(block->check) 231 : block->compressed_size; 232 233 // Initialize the check. It's caller's problem if the Check ID is not 234 // supported, and the Block decoder cannot verify the Check field. 235 // Caller can test lzma_check_is_supported(block->check). 236 coder->check_pos = 0; 237 lzma_check_init(&coder->check, block->check); 238 239 coder->ignore_check = block->version >= 1 240 ? block->ignore_check : false; 241 242 // Initialize the filter chain. 243 return lzma_raw_decoder_init(&coder->next, allocator, 244 block->filters); 245} 246 247 248extern LZMA_API(lzma_ret) 249lzma_block_decoder(lzma_stream *strm, lzma_block *block) 250{ 251 lzma_next_strm_init(lzma_block_decoder_init, strm, block); 252 253 strm->internal->supported_actions[LZMA_RUN] = true; 254 strm->internal->supported_actions[LZMA_FINISH] = true; 255 256 return LZMA_OK; 257} 258