Skip to content

Commit

Permalink
Added test for delete from in-memory zip.
Browse files Browse the repository at this point in the history
This required making some updates that are kind of hacky.
The path of least edits to miniz necessitated updating miniz
mz_zip_reader_init_mem to initialize the writer function and
additionally zip_stream_open to handle the case where a user passes
a stream and the mode 'r' or 'd'.
  • Loading branch information
prot0man committed Jan 15, 2024
1 parent 4696e96 commit 0b8109e
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/miniz.h
Original file line number Diff line number Diff line change
Expand Up @@ -5278,6 +5278,9 @@ mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index) {
((element_type *)((array_ptr)->m_p))[index]
#endif

static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
const void *pBuf, size_t n);

static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray,
mz_uint32 element_size) {
memset(pArray, 0, sizeof(mz_zip_array));
Expand Down Expand Up @@ -5994,6 +5997,14 @@ static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
return s;
}

// Intentionally wrap the mz_zip_heap_write_func logic into a different function since
// there is logic that frees the original buffer during stream close if the writer
// function is equal to mz_zip_heap_write_func.
static size_t mz_zip_mem_write_func(void *pOpaque, mz_uint64 file_ofs,
const void *pBuf, size_t n) {
return mz_zip_heap_write_func(pOpaque, file_ofs, pBuf, n);
}

mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
size_t size, mz_uint flags) {
if (!pMem)
Expand All @@ -6008,6 +6019,7 @@ mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
pZip->m_archive_size = size;
pZip->m_pRead = mz_zip_mem_read_func;
pZip->m_pWrite = mz_zip_mem_write_func;
pZip->m_pIO_opaque = pZip;
pZip->m_pNeeds_keepalive = NULL;

Expand Down
9 changes: 8 additions & 1 deletion src/zip.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,10 @@ static int zip_entry_finalize(struct zip_t *zip,
return ZIP_EOOMEM;
}

if(n == 0) {
return 0;
}

for (i = 0; i < n; ++i) {
local_header_ofs_array[i] = entry_mark[i].m_local_header_ofs;
ssize_t index = zip_sort(local_header_ofs_array, i);
Expand All @@ -609,6 +613,7 @@ static int zip_entry_finalize(struct zip_t *zip,
CLEANUP(local_header_ofs_array);
return ZIP_EOOMEM;
}

for (i = 0; i < n - 1; i++) {
length[i] =
(size_t)(local_header_ofs_array[i + 1] - local_header_ofs_array[i]);
Expand Down Expand Up @@ -1835,7 +1840,9 @@ struct zip_t *zip_stream_openwitherror(const char *stream, size_t size,
}
zip->level = (mz_uint)level;

if ((stream != NULL) && (size > 0) && (mode == 'r')) {
// for modes 'd' and 'w', would be better to use mz_zip_reader_init_writer, but there's no clean
// way to load the existing stream with that.
if ((stream != NULL) && (size > 0) && (mode == 'r' || mode == 'd' || mode == 'w')) {
if (!mz_zip_reader_init_mem(&(zip->archive), stream, size, 0)) {
*errnum = ZIP_ERINIT;
goto cleanup;
Expand Down
85 changes: 85 additions & 0 deletions test/test_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,90 @@ MU_TEST(test_entries_delete) {
zip_close(zip);
}

MU_TEST(test_entries_delete_stream) {
char *entries[] = {"delete.me", "_", "delete/file.1", "deleteme/file.3",
"delete/file.2"};
FILE *fh = NULL;
size_t zsize = 0;
uint8_t *zdata = NULL, *modified_zdata = NULL;
int rc = 0;

// read zip into in memory buffer
fh = fopen(ZIPNAME, "rb");
mu_check(fh != NULL);

rc = fseek(fh, 0L, SEEK_END);
mu_check(rc != -1);

zsize = ftell(fh);

rc = fseek(fh, 0L, SEEK_SET);
mu_check(rc != -1);

zdata = (uint8_t *)malloc(zsize);
mu_check(zdata != NULL);

rc = fread(zdata, zsize, 1, fh);
mu_check(rc >= 1);

fclose(fh);
fh = NULL;

struct zip_t *zip = zip_stream_open(zdata, zsize, 0, 'd');
mu_check(zip != NULL);

mu_assert_int_eq(5, zip_entries_delete(zip, entries, 5));

zip_stream_copy(zip, (void **)&modified_zdata, &zsize);
mu_check(modified_zdata != NULL);

zip_stream_close(zip);
free(zdata);
zdata = NULL;

zip = zip_stream_open(modified_zdata, zsize, 0, 'r');
mu_check(zip != NULL);

mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete.me"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete.me: %s\n", zip_strerror(ZIP_ENOENT));

mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "_"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "_: %s\n", zip_strerror(ZIP_ENOENT));

mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.1"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.1: %s\n", zip_strerror(ZIP_ENOENT));

mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "deleteme/file.3"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.3: %s\n", zip_strerror(ZIP_ENOENT));

mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.2"));
mu_assert_int_eq(0, zip_entry_close(zip));
fprintf(stdout, "delete/file.2: %s\n", zip_strerror(ZIP_ENOENT));

mu_assert_int_eq(total_entries - 5, zip_entries_total(zip));

mu_assert_int_eq(0, zip_entry_open(zip, "delete/file.4"));

size_t buftmp = 0;
char *buf = NULL;
ssize_t bufsize = zip_entry_read(zip, (void **)&buf, &buftmp);

mu_assert_int_eq(bufsize, strlen(TESTDATA2));
mu_assert_int_eq((size_t)bufsize, buftmp);
mu_assert_int_eq(0, strncmp(buf, TESTDATA2, bufsize));
mu_assert_int_eq(0, zip_entry_close(zip));

free(buf);
buf = NULL;

zip_stream_close(zip);
free(modified_zdata);
}

MU_TEST(test_entry_offset) {
struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
mu_check(zip != NULL);
Expand Down Expand Up @@ -423,6 +507,7 @@ MU_TEST_SUITE(test_entry_suite) {
MU_RUN_TEST(test_list_entries);
MU_RUN_TEST(test_entries_deletebyindex);
MU_RUN_TEST(test_entries_delete);
MU_RUN_TEST(test_entries_delete_stream);
MU_RUN_TEST(test_entry_offset);
}

Expand Down

0 comments on commit 0b8109e

Please sign in to comment.