2012-09-18 10 views
7

He estado usando libzip para manejar archivos zip, y he basado mi código en el ejemplo encontrado en la respuesta de rodrigo al this question. He aquí su código, para una referencia rápida:El ejemplo de Libzip contiene valores no inicializados cuando se marca con 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); 
} 

tracé los errores que obtuve posteriormente de nuevo a este Valgrind código- que se queja de un valor no inicializado al abrir la cremallera "archivo.txt" usando '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) 

No puedo ver de dónde proviene el valor no inicializado en este código. ¿Alguien puede rastrear esto o la falla reside en libzip? ¿Debo cambiar a otra biblioteca zip, por ejemplo, Minizip?

EDITAR: Los 71 bytes son los contenidos de file.txt que se leyeron en delete[] contents; etiquetados al final eliminarán eso.

(Me he dejado un comentario en la respuesta original a llamar la atención sobre el tema, pero no tengo el representante requisito.)

+0

El seguimiento de la pila es un poco extraño, usted llama a zip_fopen pero dice que está en zip_fopen_index. No puedo ver que exista un '# define' que defina en términos del otro, así que tengo que preguntar si es el correcto. –

+0

¡Estoy de acuerdo! No pude ver algo así en zip.h, era otra razón para preguntar aquí. Definitivamente el rastro correcto, lo volví a ejecutar para verificarlo. Me interesaría ver si alguien más puede reproducir esto. –

+0

Tendría que buscar en el código fuente de 'inflateReset2()' para tratar de determinar qué variable se está utilizando como condicional antes de inicializarla. El código fuente también contiene la respuesta a la pregunta 'zip_fopen_index()', estoy seguro. – twalberg

Respuesta

6

Usted me hizo mirar :)

sí, es un error dentro de zlib (utilizado por libzip), ya que tanto la asignación como el uso de la memoria están dentro de inflateInit2_ en la misma llamada. Tu código ni siquiera tiene la posibilidad de llegar a esa memoria.

Puedo repetir el problema usando zlib 1.2.3, pero ya no aparece en 1.2.7. No tenía el código para 1.2.3 disponible, pero si lo está mirando, verificaría la inicialización de state y cómo se usa dentro de inflateReset2.

Editar: Localizado el problema, descargué el paquete fuente de Ubuntu para zlib (1.2.3.4) y la línea ofensiva es;

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

wbits no se ha inicializado anterior a esta, y produzca en la advertencia. Lo extraño es que ni el zlib original 1.2.3 ni el 1.2.4 tienen este problema, parece ser exclusivo de Ubuntu. 1.2.3 ni siquiera tiene la función inflateReset2, y 1.2.4 lo tiene a la derecha;

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

desde window se ha inicializado previamente a Z_NULL, la lectura sin inicializar wbits no sucederá.

Cuestiones relacionadas