other-licenses/7zstub/src/7zip/Archive/7z/7zDecode.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 // 7zDecode.cpp
michael@0 2
michael@0 3 #include "StdAfx.h"
michael@0 4
michael@0 5 #include "7zDecode.h"
michael@0 6
michael@0 7 #include "../../IPassword.h"
michael@0 8 #include "../../Common/LockedStream.h"
michael@0 9 #include "../../Common/StreamObjects.h"
michael@0 10 #include "../../Common/ProgressUtils.h"
michael@0 11 #include "../../Common/LimitedStreams.h"
michael@0 12 #include "../Common/FilterCoder.h"
michael@0 13
michael@0 14 #include "7zMethods.h"
michael@0 15
michael@0 16 #ifdef COMPRESS_LZMA
michael@0 17 #include "../../Compress/LZMA/LZMADecoder.h"
michael@0 18 static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
michael@0 19 #endif
michael@0 20
michael@0 21 #ifdef COMPRESS_PPMD
michael@0 22 #include "../../Compress/PPMD/PPMDDecoder.h"
michael@0 23 static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
michael@0 24 #endif
michael@0 25
michael@0 26 #ifdef COMPRESS_BCJ_X86
michael@0 27 #include "../../Compress/Branch/x86.h"
michael@0 28 static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
michael@0 29 #endif
michael@0 30
michael@0 31 #ifdef COMPRESS_BCJ2
michael@0 32 #include "../../Compress/Branch/x86_2.h"
michael@0 33 static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
michael@0 34 #endif
michael@0 35
michael@0 36 #ifdef COMPRESS_DEFLATE
michael@0 37 #ifndef COMPRESS_DEFLATE_DECODER
michael@0 38 #define COMPRESS_DEFLATE_DECODER
michael@0 39 #endif
michael@0 40 #endif
michael@0 41
michael@0 42 #ifdef COMPRESS_DEFLATE_DECODER
michael@0 43 #include "../../Compress/Deflate/DeflateDecoder.h"
michael@0 44 static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
michael@0 45 #endif
michael@0 46
michael@0 47 #ifdef COMPRESS_BZIP2
michael@0 48 #ifndef COMPRESS_BZIP2_DECODER
michael@0 49 #define COMPRESS_BZIP2_DECODER
michael@0 50 #endif
michael@0 51 #endif
michael@0 52
michael@0 53 #ifdef COMPRESS_BZIP2_DECODER
michael@0 54 #include "../../Compress/BZip2/BZip2Decoder.h"
michael@0 55 static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
michael@0 56 #endif
michael@0 57
michael@0 58 #ifdef COMPRESS_COPY
michael@0 59 #include "../../Compress/Copy/CopyCoder.h"
michael@0 60 static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };
michael@0 61 #endif
michael@0 62
michael@0 63 #ifdef CRYPTO_7ZAES
michael@0 64 #include "../../Crypto/7zAES/7zAES.h"
michael@0 65 static NArchive::N7z::CMethodID k_7zAES = { { 0x6, 0xF1, 0x07, 0x01 }, 4 };
michael@0 66 #endif
michael@0 67
michael@0 68 namespace NArchive {
michael@0 69 namespace N7z {
michael@0 70
michael@0 71 static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
michael@0 72 CBindInfoEx &bindInfo)
michael@0 73 {
michael@0 74 bindInfo.Clear();
michael@0 75 int i;
michael@0 76 for (i = 0; i < folder.BindPairs.Size(); i++)
michael@0 77 {
michael@0 78 NCoderMixer2::CBindPair bindPair;
michael@0 79 bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
michael@0 80 bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
michael@0 81 bindInfo.BindPairs.Add(bindPair);
michael@0 82 }
michael@0 83 UInt32 outStreamIndex = 0;
michael@0 84 for (i = 0; i < folder.Coders.Size(); i++)
michael@0 85 {
michael@0 86 NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
michael@0 87 const CCoderInfo &coderInfo = folder.Coders[i];
michael@0 88 coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
michael@0 89 coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
michael@0 90 bindInfo.Coders.Add(coderStreamsInfo);
michael@0 91 const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
michael@0 92 bindInfo.CoderMethodIDs.Add(altCoderInfo.MethodID);
michael@0 93 for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
michael@0 94 if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
michael@0 95 bindInfo.OutStreams.Add(outStreamIndex);
michael@0 96 }
michael@0 97 for (i = 0; i < folder.PackStreams.Size(); i++)
michael@0 98 bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
michael@0 99 }
michael@0 100
michael@0 101 static bool AreCodersEqual(const NCoderMixer2::CCoderStreamsInfo &a1,
michael@0 102 const NCoderMixer2::CCoderStreamsInfo &a2)
michael@0 103 {
michael@0 104 return (a1.NumInStreams == a2.NumInStreams) &&
michael@0 105 (a1.NumOutStreams == a2.NumOutStreams);
michael@0 106 }
michael@0 107
michael@0 108 static bool AreBindPairsEqual(const NCoderMixer2::CBindPair &a1, const NCoderMixer2::CBindPair &a2)
michael@0 109 {
michael@0 110 return (a1.InIndex == a2.InIndex) &&
michael@0 111 (a1.OutIndex == a2.OutIndex);
michael@0 112 }
michael@0 113
michael@0 114 static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
michael@0 115 {
michael@0 116 if (a1.Coders.Size() != a2.Coders.Size())
michael@0 117 return false;
michael@0 118 int i;
michael@0 119 for (i = 0; i < a1.Coders.Size(); i++)
michael@0 120 if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
michael@0 121 return false;
michael@0 122 if (a1.BindPairs.Size() != a2.BindPairs.Size())
michael@0 123 return false;
michael@0 124 for (i = 0; i < a1.BindPairs.Size(); i++)
michael@0 125 if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
michael@0 126 return false;
michael@0 127 for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
michael@0 128 if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
michael@0 129 return false;
michael@0 130 if (a1.InStreams.Size() != a2.InStreams.Size())
michael@0 131 return false;
michael@0 132 if (a1.OutStreams.Size() != a2.OutStreams.Size())
michael@0 133 return false;
michael@0 134 return true;
michael@0 135 }
michael@0 136
michael@0 137 CDecoder::CDecoder(bool multiThread)
michael@0 138 {
michael@0 139 #ifndef _ST_MODE
michael@0 140 multiThread = true;
michael@0 141 #endif
michael@0 142 _multiThread = multiThread;
michael@0 143 _bindInfoExPrevIsDefinded = false;
michael@0 144 #ifndef EXCLUDE_COM
michael@0 145 LoadMethodMap();
michael@0 146 #endif
michael@0 147 }
michael@0 148
michael@0 149 HRESULT CDecoder::Decode(IInStream *inStream,
michael@0 150 UInt64 startPos,
michael@0 151 const UInt64 *packSizes,
michael@0 152 const CFolder &folderInfo,
michael@0 153 ISequentialOutStream *outStream,
michael@0 154 ICompressProgressInfo *compressProgress
michael@0 155 #ifndef _NO_CRYPTO
michael@0 156 , ICryptoGetTextPassword *getTextPassword
michael@0 157 #endif
michael@0 158 #ifdef COMPRESS_MT
michael@0 159 , bool mtMode, UInt32 numThreads
michael@0 160 #endif
michael@0 161 )
michael@0 162 {
michael@0 163 CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
michael@0 164
michael@0 165 CLockedInStream lockedInStream;
michael@0 166 lockedInStream.Init(inStream);
michael@0 167
michael@0 168 for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
michael@0 169 {
michael@0 170 CLockedSequentialInStreamImp *lockedStreamImpSpec = new
michael@0 171 CLockedSequentialInStreamImp;
michael@0 172 CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
michael@0 173 lockedStreamImpSpec->Init(&lockedInStream, startPos);
michael@0 174 startPos += packSizes[j];
michael@0 175
michael@0 176 CLimitedSequentialInStream *streamSpec = new
michael@0 177 CLimitedSequentialInStream;
michael@0 178 CMyComPtr<ISequentialInStream> inStream = streamSpec;
michael@0 179 streamSpec->Init(lockedStreamImp, packSizes[j]);
michael@0 180 inStreams.Add(inStream);
michael@0 181 }
michael@0 182
michael@0 183 int numCoders = folderInfo.Coders.Size();
michael@0 184
michael@0 185 CBindInfoEx bindInfo;
michael@0 186 ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
michael@0 187 bool createNewCoders;
michael@0 188 if (!_bindInfoExPrevIsDefinded)
michael@0 189 createNewCoders = true;
michael@0 190 else
michael@0 191 createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
michael@0 192 if (createNewCoders)
michael@0 193 {
michael@0 194 int i;
michael@0 195 _decoders.Clear();
michael@0 196 // _decoders2.Clear();
michael@0 197
michael@0 198 _mixerCoder.Release();
michael@0 199
michael@0 200 if (_multiThread)
michael@0 201 {
michael@0 202 _mixerCoderMTSpec = new NCoderMixer2::CCoderMixer2MT;
michael@0 203 _mixerCoder = _mixerCoderMTSpec;
michael@0 204 _mixerCoderCommon = _mixerCoderMTSpec;
michael@0 205 }
michael@0 206 else
michael@0 207 {
michael@0 208 #ifdef _ST_MODE
michael@0 209 _mixerCoderSTSpec = new NCoderMixer2::CCoderMixer2ST;
michael@0 210 _mixerCoder = _mixerCoderSTSpec;
michael@0 211 _mixerCoderCommon = _mixerCoderSTSpec;
michael@0 212 #endif
michael@0 213 }
michael@0 214 _mixerCoderCommon->SetBindInfo(bindInfo);
michael@0 215
michael@0 216 for (i = 0; i < numCoders; i++)
michael@0 217 {
michael@0 218 const CCoderInfo &coderInfo = folderInfo.Coders[i];
michael@0 219 const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
michael@0 220 #ifndef EXCLUDE_COM
michael@0 221 CMethodInfo methodInfo;
michael@0 222 if (!GetMethodInfo(altCoderInfo.MethodID, methodInfo))
michael@0 223 return E_NOTIMPL;
michael@0 224 #endif
michael@0 225
michael@0 226 if (coderInfo.IsSimpleCoder())
michael@0 227 {
michael@0 228 CMyComPtr<ICompressCoder> decoder;
michael@0 229 CMyComPtr<ICompressFilter> filter;
michael@0 230
michael@0 231 #ifdef COMPRESS_LZMA
michael@0 232 if (altCoderInfo.MethodID == k_LZMA)
michael@0 233 decoder = new NCompress::NLZMA::CDecoder;
michael@0 234 #endif
michael@0 235
michael@0 236 #ifdef COMPRESS_PPMD
michael@0 237 if (altCoderInfo.MethodID == k_PPMD)
michael@0 238 decoder = new NCompress::NPPMD::CDecoder;
michael@0 239 #endif
michael@0 240
michael@0 241 #ifdef COMPRESS_BCJ_X86
michael@0 242 if (altCoderInfo.MethodID == k_BCJ_X86)
michael@0 243 filter = new CBCJ_x86_Decoder;
michael@0 244 #endif
michael@0 245
michael@0 246 #ifdef COMPRESS_DEFLATE_DECODER
michael@0 247 if (altCoderInfo.MethodID == k_Deflate)
michael@0 248 decoder = new NCompress::NDeflate::NDecoder::CCOMCoder;
michael@0 249 #endif
michael@0 250
michael@0 251 #ifdef COMPRESS_BZIP2_DECODER
michael@0 252 if (altCoderInfo.MethodID == k_BZip2)
michael@0 253 decoder = new NCompress::NBZip2::CDecoder;
michael@0 254 #endif
michael@0 255
michael@0 256 #ifdef COMPRESS_COPY
michael@0 257 if (altCoderInfo.MethodID == k_Copy)
michael@0 258 decoder = new NCompress::CCopyCoder;
michael@0 259 #endif
michael@0 260
michael@0 261 #ifdef CRYPTO_7ZAES
michael@0 262 if (altCoderInfo.MethodID == k_7zAES)
michael@0 263 filter = new NCrypto::NSevenZ::CDecoder;
michael@0 264 #endif
michael@0 265
michael@0 266 if (filter)
michael@0 267 {
michael@0 268 CFilterCoder *coderSpec = new CFilterCoder;
michael@0 269 decoder = coderSpec;
michael@0 270 coderSpec->Filter = filter;
michael@0 271 }
michael@0 272 #ifndef EXCLUDE_COM
michael@0 273 if (decoder == 0)
michael@0 274 {
michael@0 275 RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath,
michael@0 276 methodInfo.Decoder, &decoder));
michael@0 277 }
michael@0 278 #endif
michael@0 279
michael@0 280 if (decoder == 0)
michael@0 281 return E_NOTIMPL;
michael@0 282
michael@0 283 _decoders.Add((IUnknown *)decoder);
michael@0 284
michael@0 285 if (_multiThread)
michael@0 286 _mixerCoderMTSpec->AddCoder(decoder);
michael@0 287 #ifdef _ST_MODE
michael@0 288 else
michael@0 289 _mixerCoderSTSpec->AddCoder(decoder, false);
michael@0 290 #endif
michael@0 291 }
michael@0 292 else
michael@0 293 {
michael@0 294 CMyComPtr<ICompressCoder2> decoder;
michael@0 295
michael@0 296 #ifdef COMPRESS_BCJ2
michael@0 297 if (altCoderInfo.MethodID == k_BCJ2)
michael@0 298 decoder = new CBCJ2_x86_Decoder;
michael@0 299 #endif
michael@0 300
michael@0 301 #ifndef EXCLUDE_COM
michael@0 302 if (decoder == 0)
michael@0 303 {
michael@0 304 RINOK(_libraries.CreateCoder2(methodInfo.FilePath,
michael@0 305 methodInfo.Decoder, &decoder));
michael@0 306 }
michael@0 307 #endif
michael@0 308
michael@0 309 if (decoder == 0)
michael@0 310 return E_NOTIMPL;
michael@0 311
michael@0 312 _decoders.Add((IUnknown *)decoder);
michael@0 313 if (_multiThread)
michael@0 314 _mixerCoderMTSpec->AddCoder2(decoder);
michael@0 315 #ifdef _ST_MODE
michael@0 316 else
michael@0 317 _mixerCoderSTSpec->AddCoder2(decoder, false);
michael@0 318 #endif
michael@0 319 }
michael@0 320 }
michael@0 321 _bindInfoExPrev = bindInfo;
michael@0 322 _bindInfoExPrevIsDefinded = true;
michael@0 323 }
michael@0 324 int i;
michael@0 325 _mixerCoderCommon->ReInit();
michael@0 326
michael@0 327 UInt32 packStreamIndex = 0, unPackStreamIndex = 0;
michael@0 328 UInt32 coderIndex = 0;
michael@0 329 // UInt32 coder2Index = 0;
michael@0 330
michael@0 331 for (i = 0; i < numCoders; i++)
michael@0 332 {
michael@0 333 const CCoderInfo &coderInfo = folderInfo.Coders[i];
michael@0 334 const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
michael@0 335 CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
michael@0 336
michael@0 337 {
michael@0 338 CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
michael@0 339 HRESULT result = decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
michael@0 340 if (setDecoderProperties)
michael@0 341 {
michael@0 342 const CByteBuffer &properties = altCoderInfo.Properties;
michael@0 343 size_t size = properties.GetCapacity();
michael@0 344 if (size > 0xFFFFFFFF)
michael@0 345 return E_NOTIMPL;
michael@0 346 if (size > 0)
michael@0 347 {
michael@0 348 RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size));
michael@0 349 }
michael@0 350 }
michael@0 351 }
michael@0 352
michael@0 353 #ifdef COMPRESS_MT
michael@0 354 if (mtMode)
michael@0 355 {
michael@0 356 CMyComPtr<ICompressSetCoderMt> setCoderMt;
michael@0 357 decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
michael@0 358 if (setCoderMt)
michael@0 359 {
michael@0 360 RINOK(setCoderMt->SetNumberOfThreads(numThreads));
michael@0 361 }
michael@0 362 }
michael@0 363 #endif
michael@0 364
michael@0 365 #ifndef _NO_CRYPTO
michael@0 366 {
michael@0 367 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
michael@0 368 HRESULT result = decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
michael@0 369 if (cryptoSetPassword)
michael@0 370 {
michael@0 371 if (getTextPassword == 0)
michael@0 372 return E_FAIL;
michael@0 373 CMyComBSTR password;
michael@0 374 RINOK(getTextPassword->CryptoGetTextPassword(&password));
michael@0 375 CByteBuffer buffer;
michael@0 376 UString unicodePassword(password);
michael@0 377 const UInt32 sizeInBytes = unicodePassword.Length() * 2;
michael@0 378 buffer.SetCapacity(sizeInBytes);
michael@0 379 for (int i = 0; i < unicodePassword.Length(); i++)
michael@0 380 {
michael@0 381 wchar_t c = unicodePassword[i];
michael@0 382 ((Byte *)buffer)[i * 2] = (Byte)c;
michael@0 383 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
michael@0 384 }
michael@0 385 RINOK(cryptoSetPassword->CryptoSetPassword(
michael@0 386 (const Byte *)buffer, sizeInBytes));
michael@0 387 }
michael@0 388 }
michael@0 389 #endif
michael@0 390
michael@0 391 coderIndex++;
michael@0 392
michael@0 393 UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
michael@0 394 UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
michael@0 395 CRecordVector<const UInt64 *> packSizesPointers;
michael@0 396 CRecordVector<const UInt64 *> unPackSizesPointers;
michael@0 397 packSizesPointers.Reserve(numInStreams);
michael@0 398 unPackSizesPointers.Reserve(numOutStreams);
michael@0 399 UInt32 j;
michael@0 400 for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
michael@0 401 unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
michael@0 402
michael@0 403 for (j = 0; j < numInStreams; j++, packStreamIndex++)
michael@0 404 {
michael@0 405 int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
michael@0 406 if (bindPairIndex >= 0)
michael@0 407 packSizesPointers.Add(
michael@0 408 &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
michael@0 409 else
michael@0 410 {
michael@0 411 int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
michael@0 412 if (index < 0)
michael@0 413 return E_FAIL;
michael@0 414 packSizesPointers.Add(&packSizes[index]);
michael@0 415 }
michael@0 416 }
michael@0 417
michael@0 418 _mixerCoderCommon->SetCoderInfo(i,
michael@0 419 &packSizesPointers.Front(),
michael@0 420 &unPackSizesPointers.Front());
michael@0 421 }
michael@0 422 UInt32 mainCoder, temp;
michael@0 423 bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
michael@0 424
michael@0 425 if (_multiThread)
michael@0 426 _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
michael@0 427 /*
michael@0 428 else
michael@0 429 _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
michael@0 430 */
michael@0 431
michael@0 432 if (numCoders == 0)
michael@0 433 return 0;
michael@0 434 CRecordVector<ISequentialInStream *> inStreamPointers;
michael@0 435 inStreamPointers.Reserve(inStreams.Size());
michael@0 436 for (i = 0; i < inStreams.Size(); i++)
michael@0 437 inStreamPointers.Add(inStreams[i]);
michael@0 438 ISequentialOutStream *outStreamPointer = outStream;
michael@0 439 return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
michael@0 440 inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
michael@0 441 }
michael@0 442
michael@0 443 }}

mercurial