1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 /// \file alone_decoder.c 4 /// \brief Decoder for LZMA_Alone files 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 "alone_decoder.h" 14 #include "lzma_decoder.h" 15 #include "lz_decoder.h" 16 17 18 struct lzma_coder_s { 19 lzma_next_coder next; 20 21 enum { 22 SEQ_PROPERTIES, 23 SEQ_DICTIONARY_SIZE, 24 SEQ_UNCOMPRESSED_SIZE, 25 SEQ_CODER_INIT, 26 SEQ_CODE, 27 } sequence; 28 29 /// Position in the header fields 30 size_t pos; 31 32 /// Uncompressed size decoded from the header 33 lzma_vli uncompressed_size; 34 35 /// Memory usage limit 36 uint64_t memlimit; 37 38 /// Amount of memory actually needed (only an estimate) 39 uint64_t memusage; 40 41 /// Options decoded from the header needed to initialize 42 /// the LZMA decoder 43 lzma_options_lzma options; 44 }; 45 46 47 static lzma_ret 48 alone_decode(lzma_coder *coder, 49 lzma_allocator *allocator lzma_attribute((__unused__)), 50 const uint8_t *restrict in, size_t *restrict in_pos, 51 size_t in_size, uint8_t *restrict out, 52 size_t *restrict out_pos, size_t out_size, 53 lzma_action action) 54 { 55 while (*out_pos < out_size 56 && (coder->sequence == SEQ_CODE || *in_pos < in_size)) 57 switch (coder->sequence) { 58 case SEQ_PROPERTIES: 59 if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos])) 60 return LZMA_FORMAT_ERROR; 61 62 coder->sequence = SEQ_DICTIONARY_SIZE; 63 ++*in_pos; 64 break; 65 66 case SEQ_DICTIONARY_SIZE: 67 coder->options.dict_size 68 |= (size_t)(in[*in_pos]) << (coder->pos * 8); 69 70 if (++coder->pos == 4) { 71 if (coder->options.dict_size != UINT32_MAX) { 72 // A hack to ditch tons of false positives: 73 // We allow only dictionary sizes that are 74 // 2^n or 2^n + 2^(n-1). LZMA_Alone created 75 // only files with 2^n, but accepts any 76 // dictionary size. If someone complains, this 77 // will be reconsidered. 78 uint32_t d = coder->options.dict_size - 1; 79 d |= d >> 2; 80 d |= d >> 3; 81 d |= d >> 4; 82 d |= d >> 8; 83 d |= d >> 16; 84 ++d; 85 86 if (d != coder->options.dict_size) 87 return LZMA_FORMAT_ERROR; 88 } 89 90 coder->pos = 0; 91 coder->sequence = SEQ_UNCOMPRESSED_SIZE; 92 } 93 94 ++*in_pos; 95 break; 96 97 case SEQ_UNCOMPRESSED_SIZE: 98 coder->uncompressed_size 99 |= (lzma_vli)(in[*in_pos]) << (coder->pos * 8); 100 ++*in_pos; 101 if (++coder->pos < 8) 102 break; 103 104 // Another hack to ditch false positives: Assume that 105 // if the uncompressed size is known, it must be less 106 // than 256 GiB. Again, if someone complains, this 107 // will be reconsidered. 108 if (coder->uncompressed_size != LZMA_VLI_UNKNOWN 109 && coder->uncompressed_size 110 >= (LZMA_VLI_C(1) << 38)) 111 return LZMA_FORMAT_ERROR; 112 113 // Calculate the memory usage so that it is ready 114 // for SEQ_CODER_INIT. 115 coder->memusage = lzma_lzma_decoder_memusage(&coder->options) 116 + LZMA_MEMUSAGE_BASE; 117 118 coder->pos = 0; 119 coder->sequence = SEQ_CODER_INIT; 120 121 // Fall through 122 123 case SEQ_CODER_INIT: { 124 if (coder->memusage > coder->memlimit) 125 return LZMA_MEMLIMIT_ERROR; 126 127 lzma_filter_info filters[2] = { 128 { 129 .init = &lzma_lzma_decoder_init, 130 .options = &coder->options, 131 }, { 132 .init = NULL, 133 } 134 }; 135 136 const lzma_ret ret = lzma_next_filter_init(&coder->next, 137 allocator, filters); 138 if (ret != LZMA_OK) 139 return ret; 140 141 // Use a hack to set the uncompressed size. 142 lzma_lz_decoder_uncompressed(coder->next.coder, 143 coder->uncompressed_size); 144 145 coder->sequence = SEQ_CODE; 146 break; 147 } 148 149 case SEQ_CODE: { 150 return coder->next.code(coder->next.coder, 151 allocator, in, in_pos, in_size, 152 out, out_pos, out_size, action); 153 } 154 155 default: 156 return LZMA_PROG_ERROR; 157 } 158 159 return LZMA_OK; 160 } 161 162 163 static void 164 alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator) 165 { 166 lzma_next_end(&coder->next, allocator); 167 lzma_free(coder, allocator); 168 return; 169 } 170 171 172 static lzma_ret 173 alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage, 174 uint64_t *old_memlimit, uint64_t new_memlimit) 175 { 176 *memusage = coder->memusage; 177 *old_memlimit = coder->memlimit; 178 179 if (new_memlimit != 0) { 180 if (new_memlimit < coder->memusage) 181 return LZMA_MEMLIMIT_ERROR; 182 183 coder->memlimit = new_memlimit; 184 } 185 186 return LZMA_OK; 187 } 188 189 190 extern lzma_ret 191 lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator, 192 uint64_t memlimit) 193 { 194 lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator); 195 196 if (memlimit == 0) 197 return LZMA_PROG_ERROR; 198 199 if (next->coder == NULL) { 200 next->coder = lzma_alloc(sizeof(lzma_coder), allocator); 201 if (next->coder == NULL) 202 return LZMA_MEM_ERROR; 203 204 next->code = &alone_decode; 205 next->end = &alone_decoder_end; 206 next->memconfig = &alone_decoder_memconfig; 207 next->coder->next = LZMA_NEXT_CODER_INIT; 208 } 209 210 next->coder->sequence = SEQ_PROPERTIES; 211 next->coder->pos = 0; 212 next->coder->options.dict_size = 0; 213 next->coder->options.preset_dict = NULL; 214 next->coder->options.preset_dict_size = 0; 215 next->coder->uncompressed_size = 0; 216 next->coder->memlimit = memlimit; 217 next->coder->memusage = LZMA_MEMUSAGE_BASE; 218 219 return LZMA_OK; 220 } 221 222 223 extern LZMA_API(lzma_ret) 224 lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit) 225 { 226 lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit); 227 228 strm->internal->supported_actions[LZMA_RUN] = true; 229 strm->internal->supported_actions[LZMA_FINISH] = true; 230 231 return LZMA_OK; 232 } 233