Hello,
Valgrind is reporting a uninitialized value problem when using xz library.

$ valgrind ./lzma-uninit-prepare
==21883== Memcheck, a memory error detector
==21883== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21883== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==21883== Command: ./lzma-uninit-prepare
==21883==
lzma 5.2.2
1 148
==21883== Conditional jump or move depends on uninitialised value(s)
==21883==    at 0x4E4329D: lz_encoder_prepare (lz_encoder.c:231)
==21883==    by 0x4E43902: lzma_lz_encoder_init (lz_encoder.c:560)
==21883==    by 0x4E39D9B: lzma_raw_coder_init (filter_common.c:286)
==21883==    by 0x4E3B6AC: block_encode_normal (block_buffer_encoder.c:189)
==21883==    by 0x4E3B6AC: block_buffer_encode.part.1
(block_buffer_encoder.c:271)
==21883==    by 0x4E3B9A0: block_buffer_encode (block_buffer_encoder.c:322)
==21883==    by 0x4E3B9A0: lzma_block_buffer_encode (block_buffer_encoder.c:323)
==21883==    by 0x4E3CDE7: lzma_stream_buffer_encode
(stream_buffer_encoder.c:96)
==21883==    by 0x4E3C0C3: lzma_easy_buffer_encode (easy_buffer_encoder.c:25)
==21883==    by 0x400913: main (lzma-uninit-prepare.c:21)
==21883==
53


Cause:
mf->size is read is lz_encoder.c:226 before initialized. mf is
allocated in lz_encoder.c:532, buffer is iniitalized, size is NOT
initialized.  gcc 4.9 apparently compiles lz_encoder.c:231 into code
that uses old_size before the buffer != NULL check occurs.

Solution:
set mf->size = 0 after allocation in lz_encoder.c:532.

Reproduce
git clone http://git.tukaani.org/xz.git && git checkout v5.2.2
./configure --prefix=$HOME/usr/local/xz && make install
make and run my reproducer.

$ cat Makefile
XZBASE = $(HOME)/usr/local/xz
CPPFLAGS = -I$(XZBASE)/include
CFLAGS = -g -O0 -std=c99
LDFLAGS = -L$(XZBASE)/lib -llzma

lzma-uninit-prepare: lzma-uninit-prepare.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(LDFLAGS)

clean:
        rm -rf lzma-uninit-prepare

$ cat lzma-uninit-prepare.c
#include <stdio.h>
#include <assert.h>
#include <malloc.h>
#include <lzma.h>

int main(void) {
    printf("lzma %s\n", lzma_version_string());
    size_t src_len = 1;
    uint8_t *src = (uint8_t *) malloc(src_len);
    assert(src);
    for (int i = 0; i < src_len; i++)
        src[i] = 0;
    size_t compress_bound = lzma_stream_buffer_bound(src_len);
    printf("%lu %lu\n", src_len, compress_bound);

    size_t dest_len = 1 + compress_bound;
    uint8_t *dest = (uint8_t *) malloc(dest_len);
    assert(dest);

    size_t compress_size = 1;
    lzma_ret lr = lzma_easy_buffer_encode(2, LZMA_CHECK_NONE, NULL,
src, src_len, dest, &compress_size, dest_len);
    assert(lr == LZMA_OK);
    printf("%lu\n", compress_size);

    free(src);
    free(dest);

    return 0;
}

Reply via email to