other-licenses/7zstub/src/7zip/Compress/Branch/x86_2.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 // x86_2.cpp
michael@0 2
michael@0 3 #include "StdAfx.h"
michael@0 4 #include "x86_2.h"
michael@0 5
michael@0 6 #include "../../../Common/Alloc.h"
michael@0 7
michael@0 8 static const int kBufferSize = 1 << 17;
michael@0 9
michael@0 10 inline bool IsJcc(Byte b0, Byte b1)
michael@0 11 {
michael@0 12 return (b0 == 0x0F && (b1 & 0xF0) == 0x80);
michael@0 13 }
michael@0 14
michael@0 15 #ifndef EXTRACT_ONLY
michael@0 16
michael@0 17 static bool inline Test86MSByte(Byte b)
michael@0 18 {
michael@0 19 return (b == 0 || b == 0xFF);
michael@0 20 }
michael@0 21
michael@0 22 bool CBCJ2_x86_Encoder::Create()
michael@0 23 {
michael@0 24 if (!_mainStream.Create(1 << 16))
michael@0 25 return false;
michael@0 26 if (!_callStream.Create(1 << 20))
michael@0 27 return false;
michael@0 28 if (!_jumpStream.Create(1 << 20))
michael@0 29 return false;
michael@0 30 if (!_rangeEncoder.Create(1 << 20))
michael@0 31 return false;
michael@0 32 if (_buffer == 0)
michael@0 33 {
michael@0 34 _buffer = (Byte *)MidAlloc(kBufferSize);
michael@0 35 if (_buffer == 0)
michael@0 36 return false;
michael@0 37 }
michael@0 38 return true;
michael@0 39 }
michael@0 40
michael@0 41 CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder()
michael@0 42 {
michael@0 43 ::MidFree(_buffer);
michael@0 44 }
michael@0 45
michael@0 46 HRESULT CBCJ2_x86_Encoder::Flush()
michael@0 47 {
michael@0 48 RINOK(_mainStream.Flush());
michael@0 49 RINOK(_callStream.Flush());
michael@0 50 RINOK(_jumpStream.Flush());
michael@0 51 _rangeEncoder.FlushData();
michael@0 52 return _rangeEncoder.FlushStream();
michael@0 53 }
michael@0 54
michael@0 55 const UInt32 kDefaultLimit = (1 << 24);
michael@0 56
michael@0 57 HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams,
michael@0 58 const UInt64 **inSizes,
michael@0 59 UInt32 numInStreams,
michael@0 60 ISequentialOutStream **outStreams,
michael@0 61 const UInt64 **outSizes,
michael@0 62 UInt32 numOutStreams,
michael@0 63 ICompressProgressInfo *progress)
michael@0 64 {
michael@0 65 if (numInStreams != 1 || numOutStreams != 4)
michael@0 66 return E_INVALIDARG;
michael@0 67
michael@0 68 if (!Create())
michael@0 69 return E_OUTOFMEMORY;
michael@0 70
michael@0 71 bool sizeIsDefined = false;
michael@0 72 UInt64 inSize;
michael@0 73 if (inSizes != NULL)
michael@0 74 if (inSizes[0] != NULL)
michael@0 75 {
michael@0 76 inSize = *inSizes[0];
michael@0 77 if (inSize <= kDefaultLimit)
michael@0 78 sizeIsDefined = true;
michael@0 79 }
michael@0 80
michael@0 81 ISequentialInStream *inStream = inStreams[0];
michael@0 82
michael@0 83 _mainStream.SetStream(outStreams[0]);
michael@0 84 _mainStream.Init();
michael@0 85 _callStream.SetStream(outStreams[1]);
michael@0 86 _callStream.Init();
michael@0 87 _jumpStream.SetStream(outStreams[2]);
michael@0 88 _jumpStream.Init();
michael@0 89 _rangeEncoder.SetStream(outStreams[3]);
michael@0 90 _rangeEncoder.Init();
michael@0 91 for (int i = 0; i < 256; i++)
michael@0 92 _statusE8Encoder[i].Init();
michael@0 93 _statusE9Encoder.Init();
michael@0 94 _statusJccEncoder.Init();
michael@0 95 CCoderReleaser releaser(this);
michael@0 96
michael@0 97 CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
michael@0 98 {
michael@0 99 inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
michael@0 100 }
michael@0 101
michael@0 102 UInt32 nowPos = 0;
michael@0 103 UInt64 nowPos64 = 0;
michael@0 104 UInt32 bufferPos = 0;
michael@0 105
michael@0 106 Byte prevByte = 0;
michael@0 107
michael@0 108 UInt64 subStreamIndex = 0;
michael@0 109 UInt64 subStreamStartPos = 0;
michael@0 110 UInt64 subStreamEndPos = 0;
michael@0 111
michael@0 112 while(true)
michael@0 113 {
michael@0 114 UInt32 processedSize = 0;
michael@0 115 while(true)
michael@0 116 {
michael@0 117 UInt32 size = kBufferSize - (bufferPos + processedSize);
michael@0 118 UInt32 processedSizeLoc;
michael@0 119 if (size == 0)
michael@0 120 break;
michael@0 121 RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));
michael@0 122 if (processedSizeLoc == 0)
michael@0 123 break;
michael@0 124 processedSize += processedSizeLoc;
michael@0 125 }
michael@0 126 UInt32 endPos = bufferPos + processedSize;
michael@0 127
michael@0 128 if (endPos < 5)
michael@0 129 {
michael@0 130 // change it
michael@0 131 for (bufferPos = 0; bufferPos < endPos; bufferPos++)
michael@0 132 {
michael@0 133 Byte b = _buffer[bufferPos];
michael@0 134 _mainStream.WriteByte(b);
michael@0 135 if (b == 0xE8)
michael@0 136 _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
michael@0 137 else if (b == 0xE9)
michael@0 138 _statusE9Encoder.Encode(&_rangeEncoder, 0);
michael@0 139 else if (IsJcc(prevByte, b))
michael@0 140 _statusJccEncoder.Encode(&_rangeEncoder, 0);
michael@0 141 prevByte = b;
michael@0 142 }
michael@0 143 return Flush();
michael@0 144 }
michael@0 145
michael@0 146 bufferPos = 0;
michael@0 147
michael@0 148 UInt32 limit = endPos - 5;
michael@0 149 while(bufferPos <= limit)
michael@0 150 {
michael@0 151 Byte b = _buffer[bufferPos];
michael@0 152 _mainStream.WriteByte(b);
michael@0 153 if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
michael@0 154 {
michael@0 155 bufferPos++;
michael@0 156 prevByte = b;
michael@0 157 continue;
michael@0 158 }
michael@0 159 Byte nextByte = _buffer[bufferPos + 4];
michael@0 160 UInt32 src =
michael@0 161 (UInt32(nextByte) << 24) |
michael@0 162 (UInt32(_buffer[bufferPos + 3]) << 16) |
michael@0 163 (UInt32(_buffer[bufferPos + 2]) << 8) |
michael@0 164 (_buffer[bufferPos + 1]);
michael@0 165 UInt32 dest = (nowPos + bufferPos + 5) + src;
michael@0 166 // if (Test86MSByte(nextByte))
michael@0 167 bool convert;
michael@0 168 if (getSubStreamSize != NULL)
michael@0 169 {
michael@0 170 UInt64 currentPos = (nowPos64 + bufferPos);
michael@0 171 while (subStreamEndPos < currentPos)
michael@0 172 {
michael@0 173 UInt64 subStreamSize;
michael@0 174 HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
michael@0 175 if (result == S_OK)
michael@0 176 {
michael@0 177 subStreamStartPos = subStreamEndPos;
michael@0 178 subStreamEndPos += subStreamSize;
michael@0 179 subStreamIndex++;
michael@0 180 }
michael@0 181 else if (result == S_FALSE || result == E_NOTIMPL)
michael@0 182 {
michael@0 183 getSubStreamSize.Release();
michael@0 184 subStreamStartPos = 0;
michael@0 185 subStreamEndPos = subStreamStartPos - 1;
michael@0 186 }
michael@0 187 else
michael@0 188 return result;
michael@0 189 }
michael@0 190 if (getSubStreamSize == NULL)
michael@0 191 {
michael@0 192 if (sizeIsDefined)
michael@0 193 convert = (dest < inSize);
michael@0 194 else
michael@0 195 convert = Test86MSByte(nextByte);
michael@0 196 }
michael@0 197 else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
michael@0 198 convert = Test86MSByte(nextByte);
michael@0 199 else
michael@0 200 {
michael@0 201 UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
michael@0 202 convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
michael@0 203 }
michael@0 204 }
michael@0 205 else if (sizeIsDefined)
michael@0 206 convert = (dest < inSize);
michael@0 207 else
michael@0 208 convert = Test86MSByte(nextByte);
michael@0 209 if (convert)
michael@0 210 {
michael@0 211 if (b == 0xE8)
michael@0 212 _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1);
michael@0 213 else if (b == 0xE9)
michael@0 214 _statusE9Encoder.Encode(&_rangeEncoder, 1);
michael@0 215 else
michael@0 216 _statusJccEncoder.Encode(&_rangeEncoder, 1);
michael@0 217
michael@0 218 bufferPos += 5;
michael@0 219 if (b == 0xE8)
michael@0 220 {
michael@0 221 _callStream.WriteByte((Byte)(dest >> 24));
michael@0 222 _callStream.WriteByte((Byte)(dest >> 16));
michael@0 223 _callStream.WriteByte((Byte)(dest >> 8));
michael@0 224 _callStream.WriteByte((Byte)(dest));
michael@0 225 }
michael@0 226 else
michael@0 227 {
michael@0 228 _jumpStream.WriteByte((Byte)(dest >> 24));
michael@0 229 _jumpStream.WriteByte((Byte)(dest >> 16));
michael@0 230 _jumpStream.WriteByte((Byte)(dest >> 8));
michael@0 231 _jumpStream.WriteByte((Byte)(dest));
michael@0 232 }
michael@0 233 prevByte = nextByte;
michael@0 234 }
michael@0 235 else
michael@0 236 {
michael@0 237 if (b == 0xE8)
michael@0 238 _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0);
michael@0 239 else if (b == 0xE9)
michael@0 240 _statusE9Encoder.Encode(&_rangeEncoder, 0);
michael@0 241 else
michael@0 242 _statusJccEncoder.Encode(&_rangeEncoder, 0);
michael@0 243 bufferPos++;
michael@0 244 prevByte = b;
michael@0 245 }
michael@0 246 }
michael@0 247 nowPos += bufferPos;
michael@0 248 nowPos64 += bufferPos;
michael@0 249
michael@0 250 if (progress != NULL)
michael@0 251 {
michael@0 252 RINOK(progress->SetRatioInfo(&nowPos64, NULL));
michael@0 253 }
michael@0 254
michael@0 255 UInt32 i = 0;
michael@0 256 while(bufferPos < endPos)
michael@0 257 _buffer[i++] = _buffer[bufferPos++];
michael@0 258 bufferPos = i;
michael@0 259 }
michael@0 260 }
michael@0 261
michael@0 262 STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams,
michael@0 263 const UInt64 **inSizes,
michael@0 264 UInt32 numInStreams,
michael@0 265 ISequentialOutStream **outStreams,
michael@0 266 const UInt64 **outSizes,
michael@0 267 UInt32 numOutStreams,
michael@0 268 ICompressProgressInfo *progress)
michael@0 269 {
michael@0 270 try
michael@0 271 {
michael@0 272 return CodeReal(inStreams, inSizes, numInStreams,
michael@0 273 outStreams, outSizes,numOutStreams, progress);
michael@0 274 }
michael@0 275 catch(const COutBufferException &e) { return e.ErrorCode; }
michael@0 276 catch(...) { return S_FALSE; }
michael@0 277 }
michael@0 278
michael@0 279 #endif
michael@0 280
michael@0 281 HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams,
michael@0 282 const UInt64 **inSizes,
michael@0 283 UInt32 numInStreams,
michael@0 284 ISequentialOutStream **outStreams,
michael@0 285 const UInt64 **outSizes,
michael@0 286 UInt32 numOutStreams,
michael@0 287 ICompressProgressInfo *progress)
michael@0 288 {
michael@0 289 if (numInStreams != 4 || numOutStreams != 1)
michael@0 290 return E_INVALIDARG;
michael@0 291
michael@0 292 if (!_mainInStream.Create(1 << 16))
michael@0 293 return E_OUTOFMEMORY;
michael@0 294 if (!_callStream.Create(1 << 20))
michael@0 295 return E_OUTOFMEMORY;
michael@0 296 if (!_jumpStream.Create(1 << 16))
michael@0 297 return E_OUTOFMEMORY;
michael@0 298 if (!_rangeDecoder.Create(1 << 20))
michael@0 299 return E_OUTOFMEMORY;
michael@0 300 if (!_outStream.Create(1 << 16))
michael@0 301 return E_OUTOFMEMORY;
michael@0 302
michael@0 303 _mainInStream.SetStream(inStreams[0]);
michael@0 304 _callStream.SetStream(inStreams[1]);
michael@0 305 _jumpStream.SetStream(inStreams[2]);
michael@0 306 _rangeDecoder.SetStream(inStreams[3]);
michael@0 307 _outStream.SetStream(outStreams[0]);
michael@0 308
michael@0 309 _mainInStream.Init();
michael@0 310 _callStream.Init();
michael@0 311 _jumpStream.Init();
michael@0 312 _rangeDecoder.Init();
michael@0 313 _outStream.Init();
michael@0 314
michael@0 315 for (int i = 0; i < 256; i++)
michael@0 316 _statusE8Decoder[i].Init();
michael@0 317 _statusE9Decoder.Init();
michael@0 318 _statusJccDecoder.Init();
michael@0 319
michael@0 320 CCoderReleaser releaser(this);
michael@0 321
michael@0 322 Byte prevByte = 0;
michael@0 323 UInt32 processedBytes = 0;
michael@0 324 while(true)
michael@0 325 {
michael@0 326 if (processedBytes > (1 << 20) && progress != NULL)
michael@0 327 {
michael@0 328 UInt64 nowPos64 = _outStream.GetProcessedSize();
michael@0 329 RINOK(progress->SetRatioInfo(NULL, &nowPos64));
michael@0 330 processedBytes = 0;
michael@0 331 }
michael@0 332 processedBytes++;
michael@0 333 Byte b;
michael@0 334 if (!_mainInStream.ReadByte(b))
michael@0 335 return Flush();
michael@0 336 _outStream.WriteByte(b);
michael@0 337 if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b))
michael@0 338 {
michael@0 339 prevByte = b;
michael@0 340 continue;
michael@0 341 }
michael@0 342 bool status;
michael@0 343 if (b == 0xE8)
michael@0 344 status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1);
michael@0 345 else if (b == 0xE9)
michael@0 346 status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1);
michael@0 347 else
michael@0 348 status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1);
michael@0 349 if (status)
michael@0 350 {
michael@0 351 UInt32 src;
michael@0 352 if (b == 0xE8)
michael@0 353 {
michael@0 354 Byte b0;
michael@0 355 if(!_callStream.ReadByte(b0))
michael@0 356 return S_FALSE;
michael@0 357 src = ((UInt32)b0) << 24;
michael@0 358 if(!_callStream.ReadByte(b0))
michael@0 359 return S_FALSE;
michael@0 360 src |= ((UInt32)b0) << 16;
michael@0 361 if(!_callStream.ReadByte(b0))
michael@0 362 return S_FALSE;
michael@0 363 src |= ((UInt32)b0) << 8;
michael@0 364 if(!_callStream.ReadByte(b0))
michael@0 365 return S_FALSE;
michael@0 366 src |= ((UInt32)b0);
michael@0 367 }
michael@0 368 else
michael@0 369 {
michael@0 370 Byte b0;
michael@0 371 if(!_jumpStream.ReadByte(b0))
michael@0 372 return S_FALSE;
michael@0 373 src = ((UInt32)b0) << 24;
michael@0 374 if(!_jumpStream.ReadByte(b0))
michael@0 375 return S_FALSE;
michael@0 376 src |= ((UInt32)b0) << 16;
michael@0 377 if(!_jumpStream.ReadByte(b0))
michael@0 378 return S_FALSE;
michael@0 379 src |= ((UInt32)b0) << 8;
michael@0 380 if(!_jumpStream.ReadByte(b0))
michael@0 381 return S_FALSE;
michael@0 382 src |= ((UInt32)b0);
michael@0 383 }
michael@0 384 UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
michael@0 385 _outStream.WriteByte((Byte)(dest));
michael@0 386 _outStream.WriteByte((Byte)(dest >> 8));
michael@0 387 _outStream.WriteByte((Byte)(dest >> 16));
michael@0 388 _outStream.WriteByte((Byte)(dest >> 24));
michael@0 389 prevByte = (dest >> 24);
michael@0 390 processedBytes += 4;
michael@0 391 }
michael@0 392 else
michael@0 393 prevByte = b;
michael@0 394 }
michael@0 395 }
michael@0 396
michael@0 397 STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams,
michael@0 398 const UInt64 **inSizes,
michael@0 399 UInt32 numInStreams,
michael@0 400 ISequentialOutStream **outStreams,
michael@0 401 const UInt64 **outSizes,
michael@0 402 UInt32 numOutStreams,
michael@0 403 ICompressProgressInfo *progress)
michael@0 404 {
michael@0 405 try
michael@0 406 {
michael@0 407 return CodeReal(inStreams, inSizes, numInStreams,
michael@0 408 outStreams, outSizes,numOutStreams, progress);
michael@0 409 }
michael@0 410 catch(const COutBufferException &e) { return e.ErrorCode; }
michael@0 411 catch(...) { return S_FALSE; }
michael@0 412 }

mercurial