Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Compress/ShrinkDecoder.cpp')
-rw-r--r--CPP/7zip/Compress/ShrinkDecoder.cpp75
1 files changed, 42 insertions, 33 deletions
diff --git a/CPP/7zip/Compress/ShrinkDecoder.cpp b/CPP/7zip/Compress/ShrinkDecoder.cpp
index bd7c2461..41f0e352 100644
--- a/CPP/7zip/Compress/ShrinkDecoder.cpp
+++ b/CPP/7zip/Compress/ShrinkDecoder.cpp
@@ -13,6 +13,7 @@
namespace NCompress {
namespace NShrink {
+static const UInt32 kEmpty = 256; // kNumItems;
static const UInt32 kBufferSize = (1 << 18);
static const unsigned kNumMinBits = 9;
@@ -34,20 +35,15 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
outBuffer.Init();
{
- unsigned i;
- for (i = 0; i < 257; i++)
- _parents[i] = (UInt16)i;
- for (; i < kNumItems; i++)
- _parents[i] = kNumItems;
- for (i = 0; i < kNumItems; i++)
- _suffixes[i] = 0;
+ for (unsigned i = 0; i < kNumItems; i++)
+ _parents[i] = kEmpty;
}
- UInt64 prevPos = 0, inPrev = 0;
+ UInt64 outPrev = 0, inPrev = 0;
unsigned numBits = kNumMinBits;
unsigned head = 257;
int lastSym = -1;
- Byte lastChar2 = 0;
+ Byte lastChar = 0;
bool moreOut = false;
HRESULT res = S_FALSE;
@@ -67,18 +63,22 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
break;
}
eofCheck = true;
- // Is specSym(=256) allowed after end of stream
- // Do we need to read it here
+ // Is specSym(=256) allowed after end of stream ?
+ // Do we need to read it here ?
}
if (progress)
{
- if (nowPos - prevPos >= (1 << 18)
- || _inProcessed - inPrev >= (1 << 20))
+ if (nowPos - outPrev >= (1 << 20) || _inProcessed - inPrev >= (1 << 20))
{
- prevPos = nowPos;
+ outPrev = nowPos;
inPrev = _inProcessed;
- RINOK(progress->SetRatioInfo(&_inProcessed, &nowPos));
+ res = progress->SetRatioInfo(&_inProcessed, &nowPos);
+ if (res != SZ_OK)
+ {
+ // break;
+ return res;
+ }
}
}
@@ -105,23 +105,30 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
continue;
}
if (sym != 2)
+ {
break;
+ // continue; // info-zip just ignores such code
+ }
{
+ /*
+ ---------- Free leaf nodes ----------
+ Note : that code can mark _parents[lastSym] as free, and next
+ inserted node will be Orphan in that case.
+ */
+
unsigned i;
- for (i = 257; i < kNumItems; i++)
+ for (i = 256; i < kNumItems; i++)
_stack[i] = 0;
for (i = 257; i < kNumItems; i++)
{
unsigned par = _parents[i];
- if (par != kNumItems)
+ if (par != kEmpty)
_stack[par] = 1;
}
for (i = 257; i < kNumItems; i++)
if (_stack[i] == 0)
- _parents[i] = kNumItems;
-
+ _parents[i] = kEmpty;
head = 257;
-
continue;
}
}
@@ -137,27 +144,22 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
bool needPrev = false;
if (head < kNumItems && lastSym >= 0)
{
- while (head < kNumItems && _parents[head] != kNumItems)
+ while (head < kNumItems && _parents[head] != kEmpty)
head++;
if (head < kNumItems)
{
- if (head == (unsigned)lastSym)
- {
- // we need to fix the code for that case
- // _parents[head] is not allowed to link to itself
- res = E_NOTIMPL;
- break;
- }
+ /*
+ if (head == lastSym), it updates Orphan to self-linked Orphan and creates two problems:
+ 1) we must check _stack[i++] overflow in code that walks tree nodes.
+ 2) self-linked node can not be removed. So such self-linked nodes can occupy all _parents items.
+ */
needPrev = true;
_parents[head] = (UInt16)lastSym;
- _suffixes[head] = (Byte)lastChar2;
+ _suffixes[head] = (Byte)lastChar;
head++;
}
}
- if (_parents[sym] == kNumItems)
- break;
-
lastSym = sym;
unsigned cur = sym;
unsigned i = 0;
@@ -166,10 +168,17 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
{
_stack[i++] = _suffixes[cur];
cur = _parents[cur];
+ // don't change that code:
+ // Orphan Check and self-linked Orphan check (_stack overflow check);
+ if (cur == kEmpty || i >= kNumItems)
+ break;
}
+ if (cur == kEmpty || i >= kNumItems)
+ break;
+
_stack[i++] = (Byte)cur;
- lastChar2 = (Byte)cur;
+ lastChar = (Byte)cur;
if (needPrev)
_suffixes[(size_t)head - 1] = (Byte)cur;