~ubuntu-branches/ubuntu/precise/p7zip/precise-security

« back to all changes in this revision

Viewing changes to CPP/7zip/Compress/Z/ZDecoder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mohammed Adnène Trojette
  • Date: 2009-02-14 20:12:27 UTC
  • mfrom: (1.1.11 upstream) (2.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090214201227-go63qxm9ozfdma60
Tags: 4.65~dfsg.1-1
* New upstream release.
* Remove wx2.8 Build-Depends added by mistakes (7zG is not yet
  intended to be built).
* Use dh_clean without -k.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// ZDecoder.cpp
2
 
 
3
 
#include "StdAfx.h"
4
 
 
5
 
#include "ZDecoder.h"
6
 
 
7
 
extern "C" 
8
 
9
 
#include "../../../../C/Alloc.h"
10
 
}
11
 
 
12
 
#include "../../Common/InBuffer.h"
13
 
#include "../../Common/OutBuffer.h"
14
 
#include "../../Common/LSBFDecoder.h"
15
 
 
16
 
namespace NCompress {
17
 
namespace NZ {
18
 
 
19
 
static const UInt32 kBufferSize = (1 << 20);
20
 
static const Byte kNumBitsMask = 0x1F;   
21
 
static const Byte kBlockModeMask = 0x80;   
22
 
static const int kNumMinBits = 9;   
23
 
static const int kNumMaxBits = 16;   
24
 
 
25
 
void CDecoder::Free()
26
 
{
27
 
  MyFree(_parents);
28
 
  _parents = 0;
29
 
  MyFree(_suffixes);
30
 
  _suffixes = 0;
31
 
  MyFree(_stack);
32
 
  _stack = 0;
33
 
}
34
 
 
35
 
bool CDecoder::Alloc(size_t numItems)
36
 
{
37
 
  Free();
38
 
  _parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16));
39
 
  if (_parents == 0)
40
 
    return false;
41
 
  _suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte));
42
 
  if (_suffixes == 0)
43
 
    return false;
44
 
  _stack = (Byte *)MyAlloc(numItems * sizeof(Byte));
45
 
  return _stack != 0;
46
 
}
47
 
 
48
 
CDecoder::~CDecoder()
49
 
{
50
 
  Free();
51
 
}
52
 
 
53
 
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
54
 
    ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */,
55
 
    ICompressProgressInfo *progress)
56
 
{
57
 
  NStream::NLSBF::CBaseDecoder<CInBuffer> inBuffer;
58
 
  COutBuffer outBuffer;
59
 
 
60
 
  if (!inBuffer.Create(kBufferSize))
61
 
    return E_OUTOFMEMORY;
62
 
  inBuffer.SetStream(inStream);
63
 
  inBuffer.Init();
64
 
 
65
 
  if (!outBuffer.Create(kBufferSize))
66
 
    return E_OUTOFMEMORY;
67
 
  outBuffer.SetStream(outStream);
68
 
  outBuffer.Init();
69
 
 
70
 
  int maxbits = _properties & kNumBitsMask;
71
 
  if (maxbits < kNumMinBits || maxbits > kNumMaxBits)
72
 
    return S_FALSE;
73
 
  UInt32 numItems = 1 << maxbits;
74
 
  bool blockMode = ((_properties & kBlockModeMask) != 0);
75
 
  if (!blockMode)
76
 
    return E_NOTIMPL;
77
 
 
78
 
  if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0)
79
 
  {
80
 
    if (!Alloc(numItems))
81
 
      return E_OUTOFMEMORY;
82
 
    _numMaxBits = maxbits;
83
 
  }
84
 
 
85
 
  UInt64 prevPos = 0;
86
 
  int numBits = kNumMinBits;
87
 
  UInt32 head = blockMode ? 257 : 256;
88
 
 
89
 
  bool needPrev = false;
90
 
 
91
 
  int keepBits = 0;
92
 
 
93
 
  _parents[256] = 0; // virus protection
94
 
  _suffixes[256] = 0;
95
 
 
96
 
  for (;;)
97
 
  {
98
 
    if (keepBits < numBits)
99
 
      keepBits = numBits * 8;
100
 
    UInt32 symbol = inBuffer.ReadBits(numBits);
101
 
    if (inBuffer.ExtraBitsWereRead())
102
 
      break;
103
 
    keepBits -= numBits;
104
 
    if (symbol >= head)
105
 
      return S_FALSE;
106
 
    if (blockMode && symbol == 256)
107
 
    {
108
 
      for (;keepBits > 0; keepBits--)
109
 
        inBuffer.ReadBits(1);
110
 
      numBits = kNumMinBits;
111
 
      head = 257;
112
 
      needPrev = false;
113
 
      continue;
114
 
    }
115
 
    UInt32 cur = symbol;
116
 
    int i = 0;
117
 
    while (cur >= 256)
118
 
    {
119
 
      _stack[i++] = _suffixes[cur];
120
 
      cur = _parents[cur];
121
 
    }
122
 
    _stack[i++] = (Byte)cur;
123
 
    if (needPrev)
124
 
    {
125
 
      _suffixes[head - 1] = (Byte)cur;
126
 
      if (symbol == head - 1)
127
 
        _stack[0] = (Byte)cur;
128
 
    }
129
 
    while (i > 0)
130
 
      outBuffer.WriteByte((_stack[--i]));
131
 
    if (head < numItems)
132
 
    {
133
 
      needPrev = true;
134
 
      _parents[head++] = (UInt16)symbol;
135
 
      if (head > ((UInt32)1 << numBits))
136
 
      {
137
 
        if (numBits < maxbits)
138
 
        {
139
 
          numBits++;
140
 
          keepBits = numBits * 8;
141
 
        }
142
 
      }
143
 
    }
144
 
    else
145
 
      needPrev = false;
146
 
 
147
 
    UInt64 nowPos = outBuffer.GetProcessedSize();
148
 
    if (progress != NULL && nowPos - prevPos > (1 << 18))
149
 
    {
150
 
      prevPos = nowPos;
151
 
      UInt64 packSize = inBuffer.GetProcessedSize();
152
 
      RINOK(progress->SetRatioInfo(&packSize, &nowPos));
153
 
    }
154
 
  }
155
 
  return outBuffer.Flush();
156
 
}
157
 
 
158
 
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
159
 
    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
160
 
    ICompressProgressInfo *progress)
161
 
{
162
 
  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
163
 
  catch(const CInBufferException &e) { return e.ErrorCode; }
164
 
  catch(const COutBufferException &e) { return e.ErrorCode; }
165
 
  catch(...) { return S_FALSE; }
166
 
}
167
 
 
168
 
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
169
 
{
170
 
  if (size < 1)
171
 
    return E_INVALIDARG;
172
 
  _properties = data[0];
173
 
  return S_OK;
174
 
}
175
 
 
176
 
}}