| OLD | NEW | 
| (Empty) |  | 
 |    1 /////////////////////////////////////////////////////////////////////////////// | 
 |    2 // | 
 |    3 /// \file       block_decoder.c | 
 |    4 /// \brief      Decodes .xz Blocks | 
 |    5 // | 
 |    6 //  Author:     Lasse Collin | 
 |    7 // | 
 |    8 //  This file has been put into the public domain. | 
 |    9 //  You can do whatever you want with this file. | 
 |   10 // | 
 |   11 /////////////////////////////////////////////////////////////////////////////// | 
 |   12  | 
 |   13 #include "block_decoder.h" | 
 |   14 #include "filter_decoder.h" | 
 |   15 #include "check.h" | 
 |   16  | 
 |   17  | 
 |   18 struct lzma_coder_s { | 
 |   19         enum { | 
 |   20                 SEQ_CODE, | 
 |   21                 SEQ_PADDING, | 
 |   22                 SEQ_CHECK, | 
 |   23         } sequence; | 
 |   24  | 
 |   25         /// The filters in the chain; initialized with lzma_raw_decoder_init(). | 
 |   26         lzma_next_coder next; | 
 |   27  | 
 |   28         /// Decoding options; we also write Compressed Size and Uncompressed | 
 |   29         /// Size back to this structure when the decoding has been finished. | 
 |   30         lzma_block *block; | 
 |   31  | 
 |   32         /// Compressed Size calculated while decoding | 
 |   33         lzma_vli compressed_size; | 
 |   34  | 
 |   35         /// Uncompressed Size calculated while decoding | 
 |   36         lzma_vli uncompressed_size; | 
 |   37  | 
 |   38         /// Maximum allowed Compressed Size; this takes into account the | 
 |   39         /// size of the Block Header and Check fields when Compressed Size | 
 |   40         /// is unknown. | 
 |   41         lzma_vli compressed_limit; | 
 |   42  | 
 |   43         /// Position when reading the Check field | 
 |   44         size_t check_pos; | 
 |   45  | 
 |   46         /// Check of the uncompressed data | 
 |   47         lzma_check_state check; | 
 |   48 }; | 
 |   49  | 
 |   50  | 
 |   51 static inline bool | 
 |   52 update_size(lzma_vli *size, lzma_vli add, lzma_vli limit) | 
 |   53 { | 
 |   54         if (limit > LZMA_VLI_MAX) | 
 |   55                 limit = LZMA_VLI_MAX; | 
 |   56  | 
 |   57         if (limit < *size || limit - *size < add) | 
 |   58                 return true; | 
 |   59  | 
 |   60         *size += add; | 
 |   61  | 
 |   62         return false; | 
 |   63 } | 
 |   64  | 
 |   65  | 
 |   66 static inline bool | 
 |   67 is_size_valid(lzma_vli size, lzma_vli reference) | 
 |   68 { | 
 |   69         return reference == LZMA_VLI_UNKNOWN || reference == size; | 
 |   70 } | 
 |   71  | 
 |   72  | 
 |   73 static lzma_ret | 
 |   74 block_decode(lzma_coder *coder, lzma_allocator *allocator, | 
 |   75                 const uint8_t *restrict in, size_t *restrict in_pos, | 
 |   76                 size_t in_size, uint8_t *restrict out, | 
 |   77                 size_t *restrict out_pos, size_t out_size, lzma_action action) | 
 |   78 { | 
 |   79         switch (coder->sequence) { | 
 |   80         case SEQ_CODE: { | 
 |   81                 const size_t in_start = *in_pos; | 
 |   82                 const size_t out_start = *out_pos; | 
 |   83  | 
 |   84                 const lzma_ret ret = coder->next.code(coder->next.coder, | 
 |   85                                 allocator, in, in_pos, in_size, | 
 |   86                                 out, out_pos, out_size, action); | 
 |   87  | 
 |   88                 const size_t in_used = *in_pos - in_start; | 
 |   89                 const size_t out_used = *out_pos - out_start; | 
 |   90  | 
 |   91                 // NOTE: We compare to compressed_limit here, which prevents | 
 |   92                 // the total size of the Block growing past LZMA_VLI_MAX. | 
 |   93                 if (update_size(&coder->compressed_size, in_used, | 
 |   94                                         coder->compressed_limit) | 
 |   95                                 || update_size(&coder->uncompressed_size, | 
 |   96                                         out_used, | 
 |   97                                         coder->block->uncompressed_size)) | 
 |   98                         return LZMA_DATA_ERROR; | 
 |   99  | 
 |  100                 lzma_check_update(&coder->check, coder->block->check, | 
 |  101                                 out + out_start, out_used); | 
 |  102  | 
 |  103                 if (ret != LZMA_STREAM_END) | 
 |  104                         return ret; | 
 |  105  | 
 |  106                 // Compressed and Uncompressed Sizes are now at their final | 
 |  107                 // values. Verify that they match the values given to us. | 
 |  108                 if (!is_size_valid(coder->compressed_size, | 
 |  109                                         coder->block->compressed_size) | 
 |  110                                 || !is_size_valid(coder->uncompressed_size, | 
 |  111                                         coder->block->uncompressed_size)) | 
 |  112                         return LZMA_DATA_ERROR; | 
 |  113  | 
 |  114                 // Copy the values into coder->block. The caller | 
 |  115                 // may use this information to construct Index. | 
 |  116                 coder->block->compressed_size = coder->compressed_size; | 
 |  117                 coder->block->uncompressed_size = coder->uncompressed_size; | 
 |  118  | 
 |  119                 coder->sequence = SEQ_PADDING; | 
 |  120         } | 
 |  121  | 
 |  122         // Fall through | 
 |  123  | 
 |  124         case SEQ_PADDING: | 
 |  125                 // Compressed Data is padded to a multiple of four bytes. | 
 |  126                 while (coder->compressed_size & 3) { | 
 |  127                         if (*in_pos >= in_size) | 
 |  128                                 return LZMA_OK; | 
 |  129  | 
 |  130                         // We use compressed_size here just get the Padding | 
 |  131                         // right. The actual Compressed Size was stored to | 
 |  132                         // coder->block already, and won't be modified by | 
 |  133                         // us anymore. | 
 |  134                         ++coder->compressed_size; | 
 |  135  | 
 |  136                         if (in[(*in_pos)++] != 0x00) | 
 |  137                                 return LZMA_DATA_ERROR; | 
 |  138                 } | 
 |  139  | 
 |  140                 if (coder->block->check == LZMA_CHECK_NONE) | 
 |  141                         return LZMA_STREAM_END; | 
 |  142  | 
 |  143                 lzma_check_finish(&coder->check, coder->block->check); | 
 |  144                 coder->sequence = SEQ_CHECK; | 
 |  145  | 
 |  146         // Fall through | 
 |  147  | 
 |  148         case SEQ_CHECK: { | 
 |  149                 const size_t check_size = lzma_check_size(coder->block->check); | 
 |  150                 lzma_bufcpy(in, in_pos, in_size, coder->block->raw_check, | 
 |  151                                 &coder->check_pos, check_size); | 
 |  152                 if (coder->check_pos < check_size) | 
 |  153                         return LZMA_OK; | 
 |  154  | 
 |  155                 // Validate the Check only if we support it. | 
 |  156                 // coder->check.buffer may be uninitialized | 
 |  157                 // when the Check ID is not supported. | 
 |  158                 if (lzma_check_is_supported(coder->block->check) | 
 |  159                                 && memcmp(coder->block->raw_check, | 
 |  160                                         coder->check.buffer.u8, | 
 |  161                                         check_size) != 0) | 
 |  162                         return LZMA_DATA_ERROR; | 
 |  163  | 
 |  164                 return LZMA_STREAM_END; | 
 |  165         } | 
 |  166         } | 
 |  167  | 
 |  168         return LZMA_PROG_ERROR; | 
 |  169 } | 
 |  170  | 
 |  171  | 
 |  172 static void | 
 |  173 block_decoder_end(lzma_coder *coder, lzma_allocator *allocator) | 
 |  174 { | 
 |  175         lzma_next_end(&coder->next, allocator); | 
 |  176         lzma_free(coder, allocator); | 
 |  177         return; | 
 |  178 } | 
 |  179  | 
 |  180  | 
 |  181 extern lzma_ret | 
 |  182 lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator, | 
 |  183                 lzma_block *block) | 
 |  184 { | 
 |  185         lzma_next_coder_init(&lzma_block_decoder_init, next, allocator); | 
 |  186  | 
 |  187         // Validate the options. lzma_block_unpadded_size() does that for us | 
 |  188         // except for Uncompressed Size and filters. Filters are validated | 
 |  189         // by the raw decoder. | 
 |  190         if (lzma_block_unpadded_size(block) == 0 | 
 |  191                         || !lzma_vli_is_valid(block->uncompressed_size)) | 
 |  192                 return LZMA_PROG_ERROR; | 
 |  193  | 
 |  194         // Allocate and initialize *next->coder if needed. | 
 |  195         if (next->coder == NULL) { | 
 |  196                 next->coder = lzma_alloc(sizeof(lzma_coder), allocator); | 
 |  197                 if (next->coder == NULL) | 
 |  198                         return LZMA_MEM_ERROR; | 
 |  199  | 
 |  200                 next->code = &block_decode; | 
 |  201                 next->end = &block_decoder_end; | 
 |  202                 next->coder->next = LZMA_NEXT_CODER_INIT; | 
 |  203         } | 
 |  204  | 
 |  205         // Basic initializations | 
 |  206         next->coder->sequence = SEQ_CODE; | 
 |  207         next->coder->block = block; | 
 |  208         next->coder->compressed_size = 0; | 
 |  209         next->coder->uncompressed_size = 0; | 
 |  210  | 
 |  211         // If Compressed Size is not known, we calculate the maximum allowed | 
 |  212         // value so that encoded size of the Block (including Block Padding) | 
 |  213         // is still a valid VLI and a multiple of four. | 
 |  214         next->coder->compressed_limit | 
 |  215                         = block->compressed_size == LZMA_VLI_UNKNOWN | 
 |  216                                 ? (LZMA_VLI_MAX & ~LZMA_VLI_C(3)) | 
 |  217                                         - block->header_size | 
 |  218                                         - lzma_check_size(block->check) | 
 |  219                                 : block->compressed_size; | 
 |  220  | 
 |  221         // Initialize the check. It's caller's problem if the Check ID is not | 
 |  222         // supported, and the Block decoder cannot verify the Check field. | 
 |  223         // Caller can test lzma_check_is_supported(block->check). | 
 |  224         next->coder->check_pos = 0; | 
 |  225         lzma_check_init(&next->coder->check, block->check); | 
 |  226  | 
 |  227         // Initialize the filter chain. | 
 |  228         return lzma_raw_decoder_init(&next->coder->next, allocator, | 
 |  229                         block->filters); | 
 |  230 } | 
 |  231  | 
 |  232  | 
 |  233 extern LZMA_API(lzma_ret) | 
 |  234 lzma_block_decoder(lzma_stream *strm, lzma_block *block) | 
 |  235 { | 
 |  236         lzma_next_strm_init(lzma_block_decoder_init, strm, block); | 
 |  237  | 
 |  238         strm->internal->supported_actions[LZMA_RUN] = true; | 
 |  239         strm->internal->supported_actions[LZMA_FINISH] = true; | 
 |  240  | 
 |  241         return LZMA_OK; | 
 |  242 } | 
| OLD | NEW |