7zDec.c (15816B)
1 /* 7zDec.c -- Decoding from 7z folder 2 2017-04-03 : Igor Pavlov : Public domain */ 3 4 #include "Precomp.h" 5 6 #include <string.h> 7 8 /* #define _7ZIP_PPMD_SUPPPORT */ 9 10 #include "7z.h" 11 #include "7zCrc.h" 12 13 #include "Bcj2.h" 14 #include "Bra.h" 15 #include "CpuArch.h" 16 #include "Delta.h" 17 #include "LzmaDec.h" 18 #include "Lzma2Dec.h" 19 #ifdef _7ZIP_PPMD_SUPPPORT 20 #include "Ppmd7.h" 21 #endif 22 23 #define k_Copy 0 24 #define k_Delta 3 25 #define k_LZMA2 0x21 26 #define k_LZMA 0x30101 27 #define k_BCJ 0x3030103 28 #define k_BCJ2 0x303011B 29 #define k_PPC 0x3030205 30 #define k_IA64 0x3030401 31 #define k_ARM 0x3030501 32 #define k_ARMT 0x3030701 33 #define k_SPARC 0x3030805 34 35 36 #ifdef _7ZIP_PPMD_SUPPPORT 37 38 #define k_PPMD 0x30401 39 40 typedef struct 41 { 42 IByteIn vt; 43 const Byte *cur; 44 const Byte *end; 45 const Byte *begin; 46 UInt64 processed; 47 Bool extra; 48 SRes res; 49 const ILookInStream *inStream; 50 } CByteInToLook; 51 52 static Byte ReadByte(const IByteIn *pp) 53 { 54 CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt); 55 if (p->cur != p->end) 56 return *p->cur++; 57 if (p->res == SZ_OK) 58 { 59 size_t size = p->cur - p->begin; 60 p->processed += size; 61 p->res = ILookInStream_Skip(p->inStream, size); 62 size = (1 << 25); 63 p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size); 64 p->cur = p->begin; 65 p->end = p->begin + size; 66 if (size != 0) 67 return *p->cur++;; 68 } 69 p->extra = True; 70 return 0; 71 } 72 73 static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream, 74 Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) 75 { 76 CPpmd7 ppmd; 77 CByteInToLook s; 78 SRes res = SZ_OK; 79 80 s.vt.Read = ReadByte; 81 s.inStream = inStream; 82 s.begin = s.end = s.cur = NULL; 83 s.extra = False; 84 s.res = SZ_OK; 85 s.processed = 0; 86 87 if (propsSize != 5) 88 return SZ_ERROR_UNSUPPORTED; 89 90 { 91 unsigned order = props[0]; 92 UInt32 memSize = GetUi32(props + 1); 93 if (order < PPMD7_MIN_ORDER || 94 order > PPMD7_MAX_ORDER || 95 memSize < PPMD7_MIN_MEM_SIZE || 96 memSize > PPMD7_MAX_MEM_SIZE) 97 return SZ_ERROR_UNSUPPORTED; 98 Ppmd7_Construct(&ppmd); 99 if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) 100 return SZ_ERROR_MEM; 101 Ppmd7_Init(&ppmd, order); 102 } 103 { 104 CPpmd7z_RangeDec rc; 105 Ppmd7z_RangeDec_CreateVTable(&rc); 106 rc.Stream = &s.vt; 107 if (!Ppmd7z_RangeDec_Init(&rc)) 108 res = SZ_ERROR_DATA; 109 else if (s.extra) 110 res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); 111 else 112 { 113 SizeT i; 114 for (i = 0; i < outSize; i++) 115 { 116 int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt); 117 if (s.extra || sym < 0) 118 break; 119 outBuffer[i] = (Byte)sym; 120 } 121 if (i != outSize) 122 res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); 123 else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) 124 res = SZ_ERROR_DATA; 125 } 126 } 127 Ppmd7_Free(&ppmd, allocMain); 128 return res; 129 } 130 131 #endif 132 133 134 static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, 135 Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) 136 { 137 CLzmaDec state; 138 SRes res = SZ_OK; 139 140 LzmaDec_Construct(&state); 141 RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); 142 state.dic = outBuffer; 143 state.dicBufSize = outSize; 144 LzmaDec_Init(&state); 145 146 for (;;) 147 { 148 const void *inBuf = NULL; 149 size_t lookahead = (1 << 18); 150 if (lookahead > inSize) 151 lookahead = (size_t)inSize; 152 res = ILookInStream_Look(inStream, &inBuf, &lookahead); 153 if (res != SZ_OK) 154 break; 155 156 { 157 SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; 158 ELzmaStatus status; 159 res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); 160 lookahead -= inProcessed; 161 inSize -= inProcessed; 162 if (res != SZ_OK) 163 break; 164 165 if (status == LZMA_STATUS_FINISHED_WITH_MARK) 166 { 167 if (outSize != state.dicPos || inSize != 0) 168 res = SZ_ERROR_DATA; 169 break; 170 } 171 172 if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) 173 break; 174 175 if (inProcessed == 0 && dicPos == state.dicPos) 176 { 177 res = SZ_ERROR_DATA; 178 break; 179 } 180 181 res = ILookInStream_Skip(inStream, inProcessed); 182 if (res != SZ_OK) 183 break; 184 } 185 } 186 187 LzmaDec_FreeProbs(&state, allocMain); 188 return res; 189 } 190 191 192 #ifndef _7Z_NO_METHOD_LZMA2 193 194 static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, 195 Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain) 196 { 197 CLzma2Dec state; 198 SRes res = SZ_OK; 199 200 Lzma2Dec_Construct(&state); 201 if (propsSize != 1) 202 return SZ_ERROR_DATA; 203 RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); 204 state.decoder.dic = outBuffer; 205 state.decoder.dicBufSize = outSize; 206 Lzma2Dec_Init(&state); 207 208 for (;;) 209 { 210 const void *inBuf = NULL; 211 size_t lookahead = (1 << 18); 212 if (lookahead > inSize) 213 lookahead = (size_t)inSize; 214 res = ILookInStream_Look(inStream, &inBuf, &lookahead); 215 if (res != SZ_OK) 216 break; 217 218 { 219 SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; 220 ELzmaStatus status; 221 res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); 222 lookahead -= inProcessed; 223 inSize -= inProcessed; 224 if (res != SZ_OK) 225 break; 226 227 if (status == LZMA_STATUS_FINISHED_WITH_MARK) 228 { 229 if (outSize != state.decoder.dicPos || inSize != 0) 230 res = SZ_ERROR_DATA; 231 break; 232 } 233 234 if (inProcessed == 0 && dicPos == state.decoder.dicPos) 235 { 236 res = SZ_ERROR_DATA; 237 break; 238 } 239 240 res = ILookInStream_Skip(inStream, inProcessed); 241 if (res != SZ_OK) 242 break; 243 } 244 } 245 246 Lzma2Dec_FreeProbs(&state, allocMain); 247 return res; 248 } 249 250 #endif 251 252 253 static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) 254 { 255 while (inSize > 0) 256 { 257 const void *inBuf; 258 size_t curSize = (1 << 18); 259 if (curSize > inSize) 260 curSize = (size_t)inSize; 261 RINOK(ILookInStream_Look(inStream, &inBuf, &curSize)); 262 if (curSize == 0) 263 return SZ_ERROR_INPUT_EOF; 264 memcpy(outBuffer, inBuf, curSize); 265 outBuffer += curSize; 266 inSize -= curSize; 267 RINOK(ILookInStream_Skip(inStream, curSize)); 268 } 269 return SZ_OK; 270 } 271 272 static Bool IS_MAIN_METHOD(UInt32 m) 273 { 274 switch (m) 275 { 276 case k_Copy: 277 case k_LZMA: 278 #ifndef _7Z_NO_METHOD_LZMA2 279 case k_LZMA2: 280 #endif 281 #ifdef _7ZIP_PPMD_SUPPPORT 282 case k_PPMD: 283 #endif 284 return True; 285 } 286 return False; 287 } 288 289 static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) 290 { 291 return 292 c->NumStreams == 1 293 /* && c->MethodID <= (UInt32)0xFFFFFFFF */ 294 && IS_MAIN_METHOD((UInt32)c->MethodID); 295 } 296 297 #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4) 298 299 static SRes CheckSupportedFolder(const CSzFolder *f) 300 { 301 if (f->NumCoders < 1 || f->NumCoders > 4) 302 return SZ_ERROR_UNSUPPORTED; 303 if (!IS_SUPPORTED_CODER(&f->Coders[0])) 304 return SZ_ERROR_UNSUPPORTED; 305 if (f->NumCoders == 1) 306 { 307 if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0) 308 return SZ_ERROR_UNSUPPORTED; 309 return SZ_OK; 310 } 311 312 313 #ifndef _7Z_NO_METHODS_FILTERS 314 315 if (f->NumCoders == 2) 316 { 317 const CSzCoderInfo *c = &f->Coders[1]; 318 if ( 319 /* c->MethodID > (UInt32)0xFFFFFFFF || */ 320 c->NumStreams != 1 321 || f->NumPackStreams != 1 322 || f->PackStreams[0] != 0 323 || f->NumBonds != 1 324 || f->Bonds[0].InIndex != 1 325 || f->Bonds[0].OutIndex != 0) 326 return SZ_ERROR_UNSUPPORTED; 327 switch ((UInt32)c->MethodID) 328 { 329 case k_Delta: 330 case k_BCJ: 331 case k_PPC: 332 case k_IA64: 333 case k_SPARC: 334 case k_ARM: 335 case k_ARMT: 336 break; 337 default: 338 return SZ_ERROR_UNSUPPORTED; 339 } 340 return SZ_OK; 341 } 342 343 #endif 344 345 346 if (f->NumCoders == 4) 347 { 348 if (!IS_SUPPORTED_CODER(&f->Coders[1]) 349 || !IS_SUPPORTED_CODER(&f->Coders[2]) 350 || !IS_BCJ2(&f->Coders[3])) 351 return SZ_ERROR_UNSUPPORTED; 352 if (f->NumPackStreams != 4 353 || f->PackStreams[0] != 2 354 || f->PackStreams[1] != 6 355 || f->PackStreams[2] != 1 356 || f->PackStreams[3] != 0 357 || f->NumBonds != 3 358 || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0 359 || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1 360 || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2) 361 return SZ_ERROR_UNSUPPORTED; 362 return SZ_OK; 363 } 364 365 return SZ_ERROR_UNSUPPORTED; 366 } 367 368 #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; 369 370 static SRes SzFolder_Decode2(const CSzFolder *folder, 371 const Byte *propsData, 372 const UInt64 *unpackSizes, 373 const UInt64 *packPositions, 374 ILookInStream *inStream, UInt64 startPos, 375 Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain, 376 Byte *tempBuf[]) 377 { 378 UInt32 ci; 379 SizeT tempSizes[3] = { 0, 0, 0}; 380 SizeT tempSize3 = 0; 381 Byte *tempBuf3 = 0; 382 383 RINOK(CheckSupportedFolder(folder)); 384 385 for (ci = 0; ci < folder->NumCoders; ci++) 386 { 387 const CSzCoderInfo *coder = &folder->Coders[ci]; 388 389 if (IS_MAIN_METHOD((UInt32)coder->MethodID)) 390 { 391 UInt32 si = 0; 392 UInt64 offset; 393 UInt64 inSize; 394 Byte *outBufCur = outBuffer; 395 SizeT outSizeCur = outSize; 396 if (folder->NumCoders == 4) 397 { 398 UInt32 indices[] = { 3, 2, 0 }; 399 UInt64 unpackSize = unpackSizes[ci]; 400 si = indices[ci]; 401 if (ci < 2) 402 { 403 Byte *temp; 404 outSizeCur = (SizeT)unpackSize; 405 if (outSizeCur != unpackSize) 406 return SZ_ERROR_MEM; 407 temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur); 408 if (!temp && outSizeCur != 0) 409 return SZ_ERROR_MEM; 410 outBufCur = tempBuf[1 - ci] = temp; 411 tempSizes[1 - ci] = outSizeCur; 412 } 413 else if (ci == 2) 414 { 415 if (unpackSize > outSize) /* check it */ 416 return SZ_ERROR_PARAM; 417 tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); 418 tempSize3 = outSizeCur = (SizeT)unpackSize; 419 } 420 else 421 return SZ_ERROR_UNSUPPORTED; 422 } 423 offset = packPositions[si]; 424 inSize = packPositions[(size_t)si + 1] - offset; 425 RINOK(LookInStream_SeekTo(inStream, startPos + offset)); 426 427 if (coder->MethodID == k_Copy) 428 { 429 if (inSize != outSizeCur) /* check it */ 430 return SZ_ERROR_DATA; 431 RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); 432 } 433 else if (coder->MethodID == k_LZMA) 434 { 435 RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); 436 } 437 #ifndef _7Z_NO_METHOD_LZMA2 438 else if (coder->MethodID == k_LZMA2) 439 { 440 RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); 441 } 442 #endif 443 #ifdef _7ZIP_PPMD_SUPPPORT 444 else if (coder->MethodID == k_PPMD) 445 { 446 RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); 447 } 448 #endif 449 else 450 return SZ_ERROR_UNSUPPORTED; 451 } 452 else if (coder->MethodID == k_BCJ2) 453 { 454 UInt64 offset = packPositions[1]; 455 UInt64 s3Size = packPositions[2] - offset; 456 457 if (ci != 3) 458 return SZ_ERROR_UNSUPPORTED; 459 460 tempSizes[2] = (SizeT)s3Size; 461 if (tempSizes[2] != s3Size) 462 return SZ_ERROR_MEM; 463 tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]); 464 if (!tempBuf[2] && tempSizes[2] != 0) 465 return SZ_ERROR_MEM; 466 467 RINOK(LookInStream_SeekTo(inStream, startPos + offset)); 468 RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])); 469 470 if ((tempSizes[0] & 3) != 0 || 471 (tempSizes[1] & 3) != 0 || 472 tempSize3 + tempSizes[0] + tempSizes[1] != outSize) 473 return SZ_ERROR_DATA; 474 475 { 476 CBcj2Dec p; 477 478 p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3; 479 p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0]; 480 p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1]; 481 p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2]; 482 483 p.dest = outBuffer; 484 p.destLim = outBuffer + outSize; 485 486 Bcj2Dec_Init(&p); 487 RINOK(Bcj2Dec_Decode(&p)); 488 489 { 490 unsigned i; 491 for (i = 0; i < 4; i++) 492 if (p.bufs[i] != p.lims[i]) 493 return SZ_ERROR_DATA; 494 495 if (!Bcj2Dec_IsFinished(&p)) 496 return SZ_ERROR_DATA; 497 498 if (p.dest != p.destLim 499 || p.state != BCJ2_STREAM_MAIN) 500 return SZ_ERROR_DATA; 501 } 502 } 503 } 504 #ifndef _7Z_NO_METHODS_FILTERS 505 else if (ci == 1) 506 { 507 if (coder->MethodID == k_Delta) 508 { 509 if (coder->PropsSize != 1) 510 return SZ_ERROR_UNSUPPORTED; 511 { 512 Byte state[DELTA_STATE_SIZE]; 513 Delta_Init(state); 514 Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize); 515 } 516 } 517 else 518 { 519 if (coder->PropsSize != 0) 520 return SZ_ERROR_UNSUPPORTED; 521 switch (coder->MethodID) 522 { 523 case k_BCJ: 524 { 525 UInt32 state; 526 x86_Convert_Init(state); 527 x86_Convert(outBuffer, outSize, 0, &state, 0); 528 break; 529 } 530 CASE_BRA_CONV(PPC) 531 CASE_BRA_CONV(IA64) 532 CASE_BRA_CONV(SPARC) 533 CASE_BRA_CONV(ARM) 534 CASE_BRA_CONV(ARMT) 535 default: 536 return SZ_ERROR_UNSUPPORTED; 537 } 538 } 539 } 540 #endif 541 else 542 return SZ_ERROR_UNSUPPORTED; 543 } 544 545 return SZ_OK; 546 } 547 548 549 SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, 550 ILookInStream *inStream, UInt64 startPos, 551 Byte *outBuffer, size_t outSize, 552 ISzAllocPtr allocMain) 553 { 554 SRes res; 555 CSzFolder folder; 556 CSzData sd; 557 558 const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; 559 sd.Data = data; 560 sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex]; 561 562 res = SzGetNextFolderItem(&folder, &sd); 563 564 if (res != SZ_OK) 565 return res; 566 567 if (sd.Size != 0 568 || folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex] 569 || outSize != SzAr_GetFolderUnpackSize(p, folderIndex)) 570 return SZ_ERROR_FAIL; 571 { 572 unsigned i; 573 Byte *tempBuf[3] = { 0, 0, 0}; 574 575 res = SzFolder_Decode2(&folder, data, 576 &p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]], 577 p->PackPositions + p->FoStartPackStreamIndex[folderIndex], 578 inStream, startPos, 579 outBuffer, (SizeT)outSize, allocMain, tempBuf); 580 581 for (i = 0; i < 3; i++) 582 ISzAlloc_Free(allocMain, tempBuf[i]); 583 584 if (res == SZ_OK) 585 if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex)) 586 if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex]) 587 res = SZ_ERROR_CRC; 588 589 return res; 590 } 591 }