kuba--/zip

Segmentation fault on entry deletion

petitnau opened this issue · 1 comments

Hi, I've encountered a problem with this library after doing some fuzzing on it.

Here's a small program that should replicate the problem.

#include "zip.h"

int main() {
    zip_t* zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');

    zip_entry_open(zip, "entry1.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry2.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry3.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry4.txt");
    zip_entry_close(zip);

    char* entries1[] = {"entry4.txt"};
    zip_entries_delete(zip, entries1, 1);

    zip_entry_open(zip, "entry5.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry6.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry7.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry8.txt");
    zip_entry_close(zip);

    char* entries2[] = {"entry8.txt"};
    zip_entries_delete(zip, entries2, 1); // Segmentation Fault

    zip_close(zip);
}

On the second zip_entries_delete, the program crashes giving me a

Segmentation fault (core dumped)

If I remove the statement at issue, the program works as expected, and creates the following zip file.
image

You cannot open zip archive for writing and delete entries at the same time (check README).
Try following fix:

#include "zip.h"

int main() {
    struct zip_t* zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
    zip_entry_open(zip, "entry1.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry2.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry3.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry4.txt");
    zip_entry_close(zip);
    zip_close(zip);


    zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'd');
    char* entries1[] = {"entry4.txt"};
    zip_entries_delete(zip, entries1, 1);
    zip_close(zip);

    zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'a');
    zip_entry_open(zip, "entry5.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry6.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry7.txt");
    zip_entry_close(zip);

    zip_entry_open(zip, "entry8.txt");
    zip_entry_close(zip);
    zip_close(zip);

    zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'd');
    char* entries2[] = {"entry8.txt"};
    zip_entries_delete(zip, entries2, 1); // Segmentation Fault
    zip_close(zip);
}