2012-09-18 10 views
7

Używam libzip do obsługi plików zip i oparłem swój kod na przykładzie znalezionym w odpowiedzi użytkownika rodrigo na this question. Oto jego kod, na podręczne:Przykład Libzip zawiera niezainicjowane wartości sprawdzane przy użyciu Valgrind

#include <zip.h> 

int main() 
{ 
    //Open the ZIP archive 
    int err = 0; 
    zip *z = zip_open("foo.zip", 0, &err); 

    //Search for the file of given name 
    const char *name = "file.txt"; 
    struct zip_stat st; 
    zip_stat_init(&st); 
    zip_stat(z, name, 0, &st); 

    //Alloc memory for its uncompressed contents 
    char *contents = new char[st.size]; 

    //Read the compressed file 
    zip_file *f = zip_fopen(z, "file.txt", 0); 
    zip_fread(f, contents, st.size); 
    zip_fclose(f); 

    //And close the archive 
    zip_close(z); 
} 

Wywiodłem błędy I później dostał od Valgrind z powrotem do tego Code narzeka od wartości zainicjalizowana podczas otwierania zip „plik.txt” używając „zip_fopen()` .

==29256== Conditional jump or move depends on uninitialised value(s) 
==29256== at 0x5B4B290: inflateReset2 (in /usr/lib/libz.so.1.2.3.4) 
==29256== by 0x5B4B37F: inflateInit2_ (in /usr/lib/libz.so.1.2.3.4) 
==29256== by 0x4E2EB8C: zip_fopen_index (in /usr/lib/libzip.so.1.0.0) 
==29256== by 0x400C32: main (main.cpp:24) 
==29256== Uninitialised value was created by a heap allocation 
==29256== at 0x4C244E8: malloc (vg_replace_malloc.c:236) 
==29256== by 0x5B4B35B: inflateInit2_ (in /usr/lib/libz.so.1.2.3.4) 
==29256== by 0x4E2EB8C: zip_fopen_index (in /usr/lib/libzip.so.1.0.0) 
==29256== by 0x400C32: main (main.cpp:24) 
==29256== 
==29256== 
==29256== HEAP SUMMARY: 
==29256==  in use at exit: 71 bytes in 1 blocks 
==29256== total heap usage: 26 allocs, 25 frees, 85,851 bytes allocated 
==29256== 
==29256== 71 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==29256== at 0x4C24A72: operator new[](unsigned long) (vg_replace_malloc.c:305) 
==29256== by 0x400BEE: main (main.cpp:19) 

Nie widzę, skąd pochodzi niezainicjowana wartość w tym kodzie. Czy ktoś może to prześledzić, czy też wina leży po stronie libzip? Czy powinienem przełączyć się na inną bibliotekę zip - na przykład Minizip?

EDYCJA: 71 bajtów jest zawartością pliku file.txt, który został odczytany w delete[] contents; oznaczony na końcu, który to wyeliminuje.

(bym pozostawił komentarz na oryginalnej odpowiedzi do zwrócenia uwagi na problem, ale nie mam wymaganego rep.)

+0

Ślad stosu jest nieco dziwny, wywołujesz zip_fopen, ale mówi, że jesteś w zip_fopen_index. Nie widzę żadnego "# define", które definiuje w kategoriach drugiego, więc musisz zapytać, czy jest to właściwy ślad stosu. –

+0

Zgadzam się! Nie mogłem zobaczyć czegoś takiego w zip.h, to był kolejny powód, żeby tu spytać. Zdecydowanie jest to właściwy ślad, po prostu uruchomiłem go ponownie, aby sprawdzić. Byłbym zainteresowany, czy ktokolwiek inny może to odtworzyć. –

+0

Trzeba by przejrzeć kod źródłowy dla 'inflateReset2()', aby spróbować określić, która zmienna jest używana jako warunkowa przed jej zainicjowaniem. Kod źródłowy zawiera także odpowiedź na pytanie 'zip_fopen_index()', jestem pewien. – twalberg

Odpowiedz

6

Zrobiłeś ze mnie :)

Tak, to błąd wewnątrz zlib (używany przez libzip), ponieważ zarówno przydział, jak i wykorzystanie pamięci są wewnątrz inflateInit2_ w tym samym wywołaniu. Twój kod nie ma nawet szansy dostać się do tej pamięci.

Mogę powtórzyć problem za pomocą Zlib 1.2.3, ale nie jest już wyświetlany w 1.2.7. Nie miałem dostępnego kodu dla wersji 1.2.3, ale jeśli się na to patrzysz, sprawdziłbym inicjalizację state i sposób jego użycia wewnątrz inflateReset2.

Edycja: Monitorowałem problem, pobrałem pakiet źródłowy Ubuntu dla zlib (1.2.3.4), a linia naruszająca to;

if (state->wbits != windowBits && state->window != Z_NULL) { 

wbits nie jest inicjowany poprzedni do tego, a spowoduje ostrzeżenie. Dziwne jest to, że ani oryginalny zlib 1.2.3 ani 1.2.4 nie mają tego problemu, wydaje się być unikalny dla Ubuntu. 1.2.3 nie ma nawet funkcji inflateReset2, a 1.2.4 ma rację;

if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { 

od window jest wcześniej inicjowane Z_NULL The niezainicjowany wbits odczytu się nie stanie.