7zDec.c 15 KB

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