| 1 | /* Lzma2Dec.c -- LZMA2 Decoder | 
|---|
| 2 | 2010-12-15 : Igor Pavlov : Public domain */ | 
|---|
| 3 |  | 
|---|
| 4 | /* #define SHOW_DEBUG_INFO */ | 
|---|
| 5 |  | 
|---|
| 6 | #ifdef SHOW_DEBUG_INFO | 
|---|
| 7 | #include <stdio.h> | 
|---|
| 8 | #endif | 
|---|
| 9 |  | 
|---|
| 10 | #include <string.h> | 
|---|
| 11 |  | 
|---|
| 12 | #include "Lzma2Dec.h" | 
|---|
| 13 |  | 
|---|
| 14 | /* | 
|---|
| 15 | 00000000  -  EOS | 
|---|
| 16 | 00000001 U U  -  Uncompressed Reset Dic | 
|---|
| 17 | 00000010 U U  -  Uncompressed No Reset | 
|---|
| 18 | 100uuuuu U U P P  -  LZMA no reset | 
|---|
| 19 | 101uuuuu U U P P  -  LZMA reset state | 
|---|
| 20 | 110uuuuu U U P P S  -  LZMA reset state + new prop | 
|---|
| 21 | 111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic | 
|---|
| 22 |  | 
|---|
| 23 | u, U - Unpack Size | 
|---|
| 24 | P - Pack Size | 
|---|
| 25 | S - Props | 
|---|
| 26 | */ | 
|---|
| 27 |  | 
|---|
| 28 | #define LZMA2_CONTROL_LZMA (1 << 7) | 
|---|
| 29 | #define LZMA2_CONTROL_COPY_NO_RESET 2 | 
|---|
| 30 | #define LZMA2_CONTROL_COPY_RESET_DIC 1 | 
|---|
| 31 | #define LZMA2_CONTROL_EOF 0 | 
|---|
| 32 |  | 
|---|
| 33 | #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) | 
|---|
| 34 |  | 
|---|
| 35 | #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3) | 
|---|
| 36 | #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2) | 
|---|
| 37 |  | 
|---|
| 38 | #define LZMA2_LCLP_MAX 4 | 
|---|
| 39 | #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) | 
|---|
| 40 |  | 
|---|
| 41 | #ifdef SHOW_DEBUG_INFO | 
|---|
| 42 | #define PRF(x) x | 
|---|
| 43 | #else | 
|---|
| 44 | #define PRF(x) | 
|---|
| 45 | #endif | 
|---|
| 46 |  | 
|---|
| 47 | typedef enum | 
|---|
| 48 | { | 
|---|
| 49 | LZMA2_STATE_CONTROL, | 
|---|
| 50 | LZMA2_STATE_UNPACK0, | 
|---|
| 51 | LZMA2_STATE_UNPACK1, | 
|---|
| 52 | LZMA2_STATE_PACK0, | 
|---|
| 53 | LZMA2_STATE_PACK1, | 
|---|
| 54 | LZMA2_STATE_PROP, | 
|---|
| 55 | LZMA2_STATE_DATA, | 
|---|
| 56 | LZMA2_STATE_DATA_CONT, | 
|---|
| 57 | LZMA2_STATE_FINISHED, | 
|---|
| 58 | LZMA2_STATE_ERROR | 
|---|
| 59 | } ELzma2State; | 
|---|
| 60 |  | 
|---|
| 61 | static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) | 
|---|
| 62 | { | 
|---|
| 63 | UInt32 dicSize; | 
|---|
| 64 | if (prop > 40) | 
|---|
| 65 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 66 | dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); | 
|---|
| 67 | props[0] = (Byte)LZMA2_LCLP_MAX; | 
|---|
| 68 | props[1] = (Byte)(dicSize); | 
|---|
| 69 | props[2] = (Byte)(dicSize >> 8); | 
|---|
| 70 | props[3] = (Byte)(dicSize >> 16); | 
|---|
| 71 | props[4] = (Byte)(dicSize >> 24); | 
|---|
| 72 | return SZ_OK; | 
|---|
| 73 | } | 
|---|
| 74 |  | 
|---|
| 75 | SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) | 
|---|
| 76 | { | 
|---|
| 77 | Byte props[LZMA_PROPS_SIZE]; | 
|---|
| 78 | RINOK(Lzma2Dec_GetOldProps(prop, props)); | 
|---|
| 79 | return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) | 
|---|
| 83 | { | 
|---|
| 84 | Byte props[LZMA_PROPS_SIZE]; | 
|---|
| 85 | RINOK(Lzma2Dec_GetOldProps(prop, props)); | 
|---|
| 86 | return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); | 
|---|
| 87 | } | 
|---|
| 88 |  | 
|---|
| 89 | void Lzma2Dec_Init(CLzma2Dec *p) | 
|---|
| 90 | { | 
|---|
| 91 | p->state = LZMA2_STATE_CONTROL; | 
|---|
| 92 | p->needInitDic = True; | 
|---|
| 93 | p->needInitState = True; | 
|---|
| 94 | p->needInitProp = True; | 
|---|
| 95 | LzmaDec_Init(&p->decoder); | 
|---|
| 96 | } | 
|---|
| 97 |  | 
|---|
| 98 | static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) | 
|---|
| 99 | { | 
|---|
| 100 | switch(p->state) | 
|---|
| 101 | { | 
|---|
| 102 | case LZMA2_STATE_CONTROL: | 
|---|
| 103 | p->control = b; | 
|---|
| 104 | PRF(printf( "\n %4X ", p->decoder.dicPos)); | 
|---|
| 105 | PRF(printf( " %2X", b)); | 
|---|
| 106 | if (p->control == 0) | 
|---|
| 107 | return LZMA2_STATE_FINISHED; | 
|---|
| 108 | if (LZMA2_IS_UNCOMPRESSED_STATE(p)) | 
|---|
| 109 | { | 
|---|
| 110 | if ((p->control & 0x7F) > 2) | 
|---|
| 111 | return LZMA2_STATE_ERROR; | 
|---|
| 112 | p->unpackSize = 0; | 
|---|
| 113 | } | 
|---|
| 114 | else | 
|---|
| 115 | p->unpackSize = (UInt32)(p->control & 0x1F) << 16; | 
|---|
| 116 | return LZMA2_STATE_UNPACK0; | 
|---|
| 117 |  | 
|---|
| 118 | case LZMA2_STATE_UNPACK0: | 
|---|
| 119 | p->unpackSize |= (UInt32)b << 8; | 
|---|
| 120 | return LZMA2_STATE_UNPACK1; | 
|---|
| 121 |  | 
|---|
| 122 | case LZMA2_STATE_UNPACK1: | 
|---|
| 123 | p->unpackSize |= (UInt32)b; | 
|---|
| 124 | p->unpackSize++; | 
|---|
| 125 | PRF(printf( " %8d", p->unpackSize)); | 
|---|
| 126 | return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; | 
|---|
| 127 |  | 
|---|
| 128 | case LZMA2_STATE_PACK0: | 
|---|
| 129 | p->packSize = (UInt32)b << 8; | 
|---|
| 130 | return LZMA2_STATE_PACK1; | 
|---|
| 131 |  | 
|---|
| 132 | case LZMA2_STATE_PACK1: | 
|---|
| 133 | p->packSize |= (UInt32)b; | 
|---|
| 134 | p->packSize++; | 
|---|
| 135 | PRF(printf( " %8d", p->packSize)); | 
|---|
| 136 | return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: | 
|---|
| 137 | (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); | 
|---|
| 138 |  | 
|---|
| 139 | case LZMA2_STATE_PROP: | 
|---|
| 140 | { | 
|---|
| 141 | int lc, lp; | 
|---|
| 142 | if (b >= (9 * 5 * 5)) | 
|---|
| 143 | return LZMA2_STATE_ERROR; | 
|---|
| 144 | lc = b % 9; | 
|---|
| 145 | b /= 9; | 
|---|
| 146 | p->decoder.prop.pb = b / 5; | 
|---|
| 147 | lp = b % 5; | 
|---|
| 148 | if (lc + lp > LZMA2_LCLP_MAX) | 
|---|
| 149 | return LZMA2_STATE_ERROR; | 
|---|
| 150 | p->decoder.prop.lc = lc; | 
|---|
| 151 | p->decoder.prop.lp = lp; | 
|---|
| 152 | p->needInitProp = False; | 
|---|
| 153 | return LZMA2_STATE_DATA; | 
|---|
| 154 | } | 
|---|
| 155 | } | 
|---|
| 156 | return LZMA2_STATE_ERROR; | 
|---|
| 157 | } | 
|---|
| 158 |  | 
|---|
| 159 | static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) | 
|---|
| 160 | { | 
|---|
| 161 | memcpy(p->dic + p->dicPos, src, size); | 
|---|
| 162 | p->dicPos += size; | 
|---|
| 163 | if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) | 
|---|
| 164 | p->checkDicSize = p->prop.dicSize; | 
|---|
| 165 | p->processedPos += (UInt32)size; | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); | 
|---|
| 169 |  | 
|---|
| 170 | SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, | 
|---|
| 171 | const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) | 
|---|
| 172 | { | 
|---|
| 173 | SizeT inSize = *srcLen; | 
|---|
| 174 | *srcLen = 0; | 
|---|
| 175 | *status = LZMA_STATUS_NOT_SPECIFIED; | 
|---|
| 176 |  | 
|---|
| 177 | while (p->state != LZMA2_STATE_FINISHED) | 
|---|
| 178 | { | 
|---|
| 179 | SizeT dicPos = p->decoder.dicPos; | 
|---|
| 180 | if (p->state == LZMA2_STATE_ERROR) | 
|---|
| 181 | return SZ_ERROR_DATA; | 
|---|
| 182 | if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) | 
|---|
| 183 | { | 
|---|
| 184 | *status = LZMA_STATUS_NOT_FINISHED; | 
|---|
| 185 | return SZ_OK; | 
|---|
| 186 | } | 
|---|
| 187 | if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) | 
|---|
| 188 | { | 
|---|
| 189 | if (*srcLen == inSize) | 
|---|
| 190 | { | 
|---|
| 191 | *status = LZMA_STATUS_NEEDS_MORE_INPUT; | 
|---|
| 192 | return SZ_OK; | 
|---|
| 193 | } | 
|---|
| 194 | (*srcLen)++; | 
|---|
| 195 | p->state = Lzma2Dec_UpdateState(p, *src++); | 
|---|
| 196 | continue; | 
|---|
| 197 | } | 
|---|
| 198 | { | 
|---|
| 199 | SizeT destSizeCur = dicLimit - dicPos; | 
|---|
| 200 | SizeT srcSizeCur = inSize - *srcLen; | 
|---|
| 201 | ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; | 
|---|
| 202 |  | 
|---|
| 203 | if (p->unpackSize <= destSizeCur) | 
|---|
| 204 | { | 
|---|
| 205 | destSizeCur = (SizeT)p->unpackSize; | 
|---|
| 206 | curFinishMode = LZMA_FINISH_END; | 
|---|
| 207 | } | 
|---|
| 208 |  | 
|---|
| 209 | if (LZMA2_IS_UNCOMPRESSED_STATE(p)) | 
|---|
| 210 | { | 
|---|
| 211 | if (*srcLen == inSize) | 
|---|
| 212 | { | 
|---|
| 213 | *status = LZMA_STATUS_NEEDS_MORE_INPUT; | 
|---|
| 214 | return SZ_OK; | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | if (p->state == LZMA2_STATE_DATA) | 
|---|
| 218 | { | 
|---|
| 219 | Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); | 
|---|
| 220 | if (initDic) | 
|---|
| 221 | p->needInitProp = p->needInitState = True; | 
|---|
| 222 | else if (p->needInitDic) | 
|---|
| 223 | return SZ_ERROR_DATA; | 
|---|
| 224 | p->needInitDic = False; | 
|---|
| 225 | LzmaDec_InitDicAndState(&p->decoder, initDic, False); | 
|---|
| 226 | } | 
|---|
| 227 |  | 
|---|
| 228 | if (srcSizeCur > destSizeCur) | 
|---|
| 229 | srcSizeCur = destSizeCur; | 
|---|
| 230 |  | 
|---|
| 231 | if (srcSizeCur == 0) | 
|---|
| 232 | return SZ_ERROR_DATA; | 
|---|
| 233 |  | 
|---|
| 234 | LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); | 
|---|
| 235 |  | 
|---|
| 236 | src += srcSizeCur; | 
|---|
| 237 | *srcLen += srcSizeCur; | 
|---|
| 238 | p->unpackSize -= (UInt32)srcSizeCur; | 
|---|
| 239 | p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; | 
|---|
| 240 | } | 
|---|
| 241 | else | 
|---|
| 242 | { | 
|---|
| 243 | SizeT outSizeProcessed; | 
|---|
| 244 | SRes res; | 
|---|
| 245 |  | 
|---|
| 246 | if (p->state == LZMA2_STATE_DATA) | 
|---|
| 247 | { | 
|---|
| 248 | int mode = LZMA2_GET_LZMA_MODE(p); | 
|---|
| 249 | Bool initDic = (mode == 3); | 
|---|
| 250 | Bool initState = (mode > 0); | 
|---|
| 251 | if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) | 
|---|
| 252 | return SZ_ERROR_DATA; | 
|---|
| 253 |  | 
|---|
| 254 | LzmaDec_InitDicAndState(&p->decoder, initDic, initState); | 
|---|
| 255 | p->needInitDic = False; | 
|---|
| 256 | p->needInitState = False; | 
|---|
| 257 | p->state = LZMA2_STATE_DATA_CONT; | 
|---|
| 258 | } | 
|---|
| 259 | if (srcSizeCur > p->packSize) | 
|---|
| 260 | srcSizeCur = (SizeT)p->packSize; | 
|---|
| 261 |  | 
|---|
| 262 | res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); | 
|---|
| 263 |  | 
|---|
| 264 | src += srcSizeCur; | 
|---|
| 265 | *srcLen += srcSizeCur; | 
|---|
| 266 | p->packSize -= (UInt32)srcSizeCur; | 
|---|
| 267 |  | 
|---|
| 268 | outSizeProcessed = p->decoder.dicPos - dicPos; | 
|---|
| 269 | p->unpackSize -= (UInt32)outSizeProcessed; | 
|---|
| 270 |  | 
|---|
| 271 | RINOK(res); | 
|---|
| 272 | if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) | 
|---|
| 273 | return res; | 
|---|
| 274 |  | 
|---|
| 275 | if (srcSizeCur == 0 && outSizeProcessed == 0) | 
|---|
| 276 | { | 
|---|
| 277 | if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || | 
|---|
| 278 | p->unpackSize != 0 || p->packSize != 0) | 
|---|
| 279 | return SZ_ERROR_DATA; | 
|---|
| 280 | p->state = LZMA2_STATE_CONTROL; | 
|---|
| 281 | } | 
|---|
| 282 | if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) | 
|---|
| 283 | *status = LZMA_STATUS_NOT_FINISHED; | 
|---|
| 284 | } | 
|---|
| 285 | } | 
|---|
| 286 | } | 
|---|
| 287 | *status = LZMA_STATUS_FINISHED_WITH_MARK; | 
|---|
| 288 | return SZ_OK; | 
|---|
| 289 | } | 
|---|
| 290 |  | 
|---|
| 291 | SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) | 
|---|
| 292 | { | 
|---|
| 293 | SizeT outSize = *destLen, inSize = *srcLen; | 
|---|
| 294 | *srcLen = *destLen = 0; | 
|---|
| 295 | for (;;) | 
|---|
| 296 | { | 
|---|
| 297 | SizeT srcSizeCur = inSize, outSizeCur, dicPos; | 
|---|
| 298 | ELzmaFinishMode curFinishMode; | 
|---|
| 299 | SRes res; | 
|---|
| 300 | if (p->decoder.dicPos == p->decoder.dicBufSize) | 
|---|
| 301 | p->decoder.dicPos = 0; | 
|---|
| 302 | dicPos = p->decoder.dicPos; | 
|---|
| 303 | if (outSize > p->decoder.dicBufSize - dicPos) | 
|---|
| 304 | { | 
|---|
| 305 | outSizeCur = p->decoder.dicBufSize; | 
|---|
| 306 | curFinishMode = LZMA_FINISH_ANY; | 
|---|
| 307 | } | 
|---|
| 308 | else | 
|---|
| 309 | { | 
|---|
| 310 | outSizeCur = dicPos + outSize; | 
|---|
| 311 | curFinishMode = finishMode; | 
|---|
| 312 | } | 
|---|
| 313 |  | 
|---|
| 314 | res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); | 
|---|
| 315 | src += srcSizeCur; | 
|---|
| 316 | inSize -= srcSizeCur; | 
|---|
| 317 | *srcLen += srcSizeCur; | 
|---|
| 318 | outSizeCur = p->decoder.dicPos - dicPos; | 
|---|
| 319 | memcpy(dest, p->decoder.dic + dicPos, outSizeCur); | 
|---|
| 320 | dest += outSizeCur; | 
|---|
| 321 | outSize -= outSizeCur; | 
|---|
| 322 | *destLen += outSizeCur; | 
|---|
| 323 | if (res != 0) | 
|---|
| 324 | return res; | 
|---|
| 325 | if (outSizeCur == 0 || outSize == 0) | 
|---|
| 326 | return SZ_OK; | 
|---|
| 327 | } | 
|---|
| 328 | } | 
|---|
| 329 |  | 
|---|
| 330 | SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, | 
|---|
| 331 | Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) | 
|---|
| 332 | { | 
|---|
| 333 | CLzma2Dec p; | 
|---|
| 334 | SRes res; | 
|---|
| 335 | SizeT outSize = *destLen, inSize = *srcLen; | 
|---|
| 336 | *destLen = *srcLen = 0; | 
|---|
| 337 | *status = LZMA_STATUS_NOT_SPECIFIED; | 
|---|
| 338 | Lzma2Dec_Construct(&p); | 
|---|
| 339 | RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); | 
|---|
| 340 | p.decoder.dic = dest; | 
|---|
| 341 | p.decoder.dicBufSize = outSize; | 
|---|
| 342 | Lzma2Dec_Init(&p); | 
|---|
| 343 | *srcLen = inSize; | 
|---|
| 344 | res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); | 
|---|
| 345 | *destLen = p.decoder.dicPos; | 
|---|
| 346 | if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) | 
|---|
| 347 | res = SZ_ERROR_INPUT_EOF; | 
|---|
| 348 | Lzma2Dec_FreeProbs(&p, alloc); | 
|---|
| 349 | return res; | 
|---|
| 350 | } | 
|---|
| 351 |  | 
|---|