Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added test for delete from in-memory zip. #333

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ jobs:
cmake --build build
tree -sha build
- name: Test
run: ASAN_OPTIONS=detect_leaks=0 LSAN_OPTIONS=verbosity=1:log_threads=1 cmake --build build --target test
run: |
cd build
ASAN_OPTIONS=detect_leaks=0 LSAN_OPTIONS=verbosity=1:log_threads=1 CTEST_OUTPUT_ON_FAILURE=1 ctest -VV --output-on-failure

macos:
runs-on: macos-latest
Expand All @@ -33,7 +35,9 @@ jobs:
cmake --build build
tree -sha build
- name: Test
run: cmake --build build --target test
run: |
cd build
CTEST_OUTPUT_ON_FAILURE=1 ctest -VV --output-on-failure

# freebsd:
# runs-on: macos-latest
Expand Down Expand Up @@ -63,7 +67,7 @@ jobs:
- name: Test
run: |
cd build
ctest -VV -C "Debug"
ctest -VV -C "Debug" --output-on-failure

windows-mingw:
runs-on: "windows-latest"
Expand All @@ -76,4 +80,6 @@ jobs:
cmake --build build
tree /a /f build
- name: Test
run: cmake --build build --target test
run: |
cd build
ctest -VV -C "Debug" --output-on-failure
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14)
cmake_minimum_required(VERSION 3.17)

project(zip
LANGUAGES C
Expand Down
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
20 changes: 18 additions & 2 deletions src/zip.c
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,11 @@ static int zip_entry_finalize(struct zip_t *zip,
const ssize_t n) {

ssize_t i = 0;

if(n == 0) {
return 0;
kuba-- marked this conversation as resolved.
Show resolved Hide resolved
}

mz_uint64 *local_header_ofs_array = (mz_uint64 *)calloc(n, sizeof(mz_uint64));
if (!local_header_ofs_array) {
return ZIP_EOOMEM;
Expand All @@ -609,6 +614,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,8 +1841,18 @@ struct zip_t *zip_stream_openwitherror(const char *stream, size_t size,
}
zip->level = (mz_uint)level;

if ((stream != NULL) && (size > 0) && (mode == 'r')) {
if (!mz_zip_reader_init_mem(&(zip->archive), stream, size, 0)) {
// 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')) {
uint8_t *stream_copy = (uint8_t *)malloc(size);

if(!stream_copy) {
*errnum = ZIP_EOOMEM;
goto cleanup;
}
memcpy(stream_copy, stream, size);

if (!mz_zip_reader_init_mem(&(zip->archive), stream_copy, size, 0)) {
*errnum = ZIP_ERINIT;
kuba-- marked this conversation as resolved.
Show resolved Hide resolved
goto cleanup;
}
Expand Down
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14)
cmake_minimum_required(VERSION 3.17)

find_package(Sanitizers)

Expand Down
88 changes: 88 additions & 0 deletions test/test_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,93 @@ 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, sizeof(uint8_t), zsize, 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);

free(zdata);
zdata = NULL;

// Note that zip_stream_close will free the zdata passed in zip_stream_open
zip_stream_close(zip);
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 +510,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
Loading