7

私はlibzipを使用してzipファイルを処理しており、この質問に対するrodrigoの回答にある例に基づいてコードを作成しました。クイックリファレンス用に、彼のコードは次のとおりです。

#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);
}

その後 Valgrind から取得したエラーをこのコードまでたどりました。「zip_fopen()」を使用して圧縮された「file.txt」を開くと、初期化されていない値が表示されます。

==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)

このコードでは、初期化されていない値がどこから来ているのかわかりません。誰でもこれを追跡できますか、それとも libzip 自体に問題がありますか? Minizip などの別の zip ライブラリに切り替える必要がありますか?

編集: 71 バイトは file.txt の内容でありdelete[] contents;、最後にタグ付けされて読み込まれ、それが削除されます。

(問題に注意を引くために元の回答にコメントを残していたはずですが、必要な担当者がいません。)

4

1 に答える 1

6

あなたは私を見せました:)

inflateInit2_はい、メモリの割り当てと使用の両方が同じ呼び出しで行われるため、zlib (libzip によって使用される) 内のエラーです。あなたのコードには、そのメモリに到達する機会すらありません。

zlib 1.2.3 を使用して問題を繰り返すことができますが、1.2.7 では表示されなくなりました。1.2.3 のコードは入手できませんでしたが、見ている場合は、 の初期化stateと内部での使用方法を確認しますinflateReset2

編集:問題を追跡し、zlib(1.2.3.4)用のUbuntuのソースパッケージをダウンロードしましたが、問題のある行は次のとおりです。

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

wbitsこれより前に初期化されていないため、警告が発生します。奇妙なことに、元の zlib 1.2.3 または 1.2.4 にはこの問題がなく、Ubuntu に固有のようです。1.2.3 には関数 inflateReset2 さえありませんが、1.2.4 にはそれがあります。

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

以前windowに Z_NULL に初期化されているため、初期化されていないwbits読み取りは発生しません。

于 2012-09-18T21:26:03.417 に答える