[squeak-dev] Buffer overrun in ZipPlugin

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Mar 31 21:05:42 UTC 2017


I believe that the problem lies in DeflateStream>>deflateBlock

Especially the lines that compute lastIndex:

    [blockPosition < position] whileTrue:[
        (position + MaxMatch > writeLimit)
            ifTrue:[lastIndex := writeLimit - MaxMatch]
            ifFalse:[lastIndex := position].

Because the expectations below is:
deflateBlock: lastIndex chainLength: chainLength goodMatch: goodMatch
    "Continue deflating the receiver's collection from blockPosition to
lastIndex.
    Note that lastIndex must be at least MaxMatch away from the end of
collection"

And because lastIndex and position are 0 based.
While writeLimit is a size (65536).

I think that the code should rather be:

    [blockPosition < position] whileTrue:[
        (position + MaxMatch + 1 > writeLimit)
            ifTrue:[lastIndex := writeLimit - MaxMatch - 1]
            ifFalse:[lastIndex := position].

My failing example pass with above patch.
I'm about to commit it.
Before I do so, are there some extensive tests for zlib?

2017-03-31 21:13 GMT+02:00 Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com>:

> Hi,
> some remember that from time to time, especially when the ZipPlugin is
> disabled, the DeflateStream fallback code is failing with a 'subscript is
> out of bounds: 65537'
>
> I have a reproducible example with quite a large file
>
>     | zip file |
>     zip := (FileStream fileNamed: 'snapshot.bin.gz') binary
> contentsOfEntireFile asString.
>     file := zip unzipped.
>     file zipped unzipped = file
>
> which gives me:
>
> ByteString(Object)>>error:
> ByteString(Object)>>errorSubscriptBounds:
> ByteString(Object)>>at:
> ByteString>>at:
> ByteString>>byteAt:
> GZipWriteStream(DeflateStream)>>updateHashAt:
> GZipWriteStream(DeflateStream)>>insertStringAt:
> GZipWriteStream(DeflateStream)>>deflateBlock:chainLength:goodMatch:
> GZipWriteStream(ZipWriteStream)>>deflateBlock:chainLength:goodMatch:
> GZipWriteStream(DeflateStream)>>deflateBlock
> GZipWriteStream(DeflateStream)>>next:putAll:startingAt:
> GZipWriteStream(DeflateStream)>>nextPutAll:
> ByteString(String)>>zipped
>
> When the plugin is enabled, the example works.
> So I've been tracking the differences between DeflatePlugin and
> DeflateStream fallback code for some times without success.
>
> What if I add a bound check in the DeflatePlugin?
> Then the plugin equally fails. I mean it reads past zipCollection bounds.
>
> So there's something bad in the implementation.
> Why does the example seem to work is still mysterious to me.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20170331/a5a122f2/attachment.html>


More information about the Squeak-dev mailing list