Re: Valgrind updates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Tue, 27 Jan 2009, Johannes Schindelin wrote:
> 
> Come to think of it, the word "suppression" is probably a good indicator 
> that valgrind never claimed it would mark the zlib buffer as properly 
> initialized.

Hmm. The zlib faq has a note about zlib doing a conditional on 
uninitialized memory that doesn't matter, and that is what the suppression 
should be about (to avoid a warning about "Conditional jump or move 
depends on uninitialised value").

But that one is documented to not matter for the actual output (zlib 
FAQ#36).

It's possible that zlib really does leave padding bytes around that 
literally don't matter, and that don't get initialized. That really would 
be bad, because it means that the output of git wouldn't be repeatable. 
But I doubt this is the case - original git used to actually do the SHA1 
over the _compressed_ data, which was admittedly a totally and utterly 
broken design (and we fixed it), but it did work. Maybe it worked by luck, 
but I somehow doubt it.

Some googling did find this:

	http://mailman.few.vu.nl/pipermail/sysprog/2008-October/000298.html

which looks very similar: an uninitialized byte in the middle of a 
deflate() packet.

Anyway, I'm just going to Cc 'zlib@xxxxxxxx', since this definitely is 
_not_ the same issue as in the FAQ, and we're not the only ones seeing it. 
For the zlib people: the code is literally this:

        /* Set it up */
        memset(&stream, 0, sizeof(stream));
        deflateInit(&stream, zlib_compression_level);
        size = 8 + deflateBound(&stream, len+hdrlen);
        compressed = xmalloc(size);

        /* Compress it */
        stream.next_out = compressed;
        stream.avail_out = size;

        /* First header.. */
        stream.next_in = (unsigned char *)hdr;
        stream.avail_in = hdrlen;
        while (deflate(&stream, 0) == Z_OK)
                /* nothing */;

        /* Then the data itself.. */
        stream.next_in = buf;
        stream.avail_in = len;
        ret = deflate(&stream, Z_FINISH);
        if (ret != Z_STREAM_END)
                die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret);

        ret = deflateEnd(&stream);
        if (ret != Z_OK)
                die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret);

        size = stream.total_out;

        if (write_buffer(fd, compressed, size) < 0)
                die("unable to write sha1 file");

and valgrind complains that the "write_buffer()" call will touch an 
uninitialized byte (just one byte, and in the _middle_ of the buffer, no 
less):

> Yet, the buffer in question is 195 bytes, stream.total_count (which 
> totally agrees with size - stream.avail_out) says it is 58 bytes, and 
> valgrind says that the byte with offset 51 is uninitialized.

The thing to note here is that what we are passing in to "write_buffer()" 
is _exactly_ what zlib deflated for us:

 - 'compressed' is the allocation, and is what we used to initialize 
   'stream.next_out' with (at the top of the code sequence above)

 - 'size' is gotten from 'stream.total_out' at the end of the compression.

Maybe the zlib people can tell us that we're idiots and the above is 
buggy, but maybe there is a real bug in zlib. Maybe it's triggered by our 
use of using two different input buffers to deflate() (ie we compress the 
header first, and then the body of the actual data, and put it all in one 
single output buffer), which may be unusual usage of zlib routines and may 
be why there aren't tons of reports of this.

(Our use of just depending on deflate() returning Z_BUF_ERROR after 
consuming all of the header data is probably also "unusual", but the 
manual explicitly says that it's not fatal and that deflate can be called 
again with more buffers).

Oh Gods of zlib, please hear our plea for clarification..

			Linus
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux