diff options
Diffstat (limited to 'libgo/go/compress/lzw/reader.go')
-rw-r--r-- | libgo/go/compress/lzw/reader.go | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/libgo/go/compress/lzw/reader.go b/libgo/go/compress/lzw/reader.go index 9eef2b2a782..1be52d55e4f 100644 --- a/libgo/go/compress/lzw/reader.go +++ b/libgo/go/compress/lzw/reader.go @@ -57,8 +57,14 @@ type decoder struct { // The next two codes mean clear and EOF. // Other valid codes are in the range [lo, hi] where lo := clear + 2, // with the upper bound incrementing on each code seen. - // overflow is the code at which hi overflows the code width. + // + // overflow is the code at which hi overflows the code width. It always + // equals 1 << width. + // // last is the most recently seen code, or decoderInvalidCode. + // + // An invariant is that + // (hi < overflow) || (hi == overflow && last == decoderInvalidCode) clear, eof, hi, overflow, last uint16 // Each code c in [lo, hi] expands to two or more bytes. For c != hi: @@ -163,7 +169,7 @@ loop: break loop case code <= d.hi: c, i := code, len(d.output)-1 - if code == d.hi { + if code == d.hi && d.last != decoderInvalidCode { // code == hi is a special case which expands to the last expansion // followed by the head of the last expansion. To find the head, we walk // the prefix chain until we find a literal code. @@ -196,6 +202,10 @@ loop: if d.hi >= d.overflow { if d.width == maxWidth { d.last = decoderInvalidCode + // Undo the d.hi++ a few lines above, so that (1) we maintain + // the invariant that d.hi <= d.overflow, and (2) d.hi does not + // eventually overflow a uint16. + d.hi-- } else { d.width++ d.overflow <<= 1 |