From fc73b14b2477c9ffe6c3df76ce00ea00b675a68d Mon Sep 17 00:00:00 2001 From: Atharv Mantri Date: Mon, 14 Sep 2026 08:49:02 +0530 Subject: [PATCH 1/2] Fix: terminate truncated Minizip filenames --- contrib/minizip/unzip.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/minizip/unzip.c b/contrib/minizip/unzip.c index 827c23a12b..7bd572625c 100644 --- a/contrib/minizip/unzip.c +++ b/contrib/minizip/unzip.c @@ -860,7 +860,11 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file, uSizeRead = file_info.size_filename; } else - uSizeRead = fileNameBufferSize; + { + uSizeRead = (fileNameBufferSize > 0) ? fileNameBufferSize - 1 : 0; + if (fileNameBufferSize > 0) + *(szFileName+uSizeRead)='\0'; + } if ((file_info.size_filename>0) && (fileNameBufferSize>0)) if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) From 559739a9fa3665a848c4abda2d0f6dc9d09cb7e3 Mon Sep 17 00:00:00 2001 From: Atharv Mantri Date: Tue, 15 Sep 2026 09:19:45 +0530 Subject: [PATCH 2/2] Add truncated filename termination regression test --- contrib/minizip/test/CMakeLists.txt | 14 ++++ .../minizip/test/unzip_filename_termination.c | 82 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 contrib/minizip/test/unzip_filename_termination.c diff --git a/contrib/minizip/test/CMakeLists.txt b/contrib/minizip/test/CMakeLists.txt index a909a24281..22068f4703 100644 --- a/contrib/minizip/test/CMakeLists.txt +++ b/contrib/minizip/test/CMakeLists.txt @@ -1,4 +1,18 @@ # if we are built from with zlib, use this path's) + +set(MINIZIP_TEST_LIBRARY MINIZIP::minizipstatic) + +add_executable( + ${ZLIB_CONTRIB_PREFIX}minizip_filename_termination_test + unzip_filename_termination.c) +target_link_libraries( + ${ZLIB_CONTRIB_PREFIX}minizip_filename_termination_test + PRIVATE ${MINIZIP_TEST_LIBRARY}) +add_test( + NAME ${ZLIB_CONTRIB_PREFIX}minizip_filename_termination_test + COMMAND ${ZLIB_CONTRIB_PREFIX}minizip_filename_termination_test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + if(ZLIB_MINIZIP_INSTALL) if(NOT DEFINED ZLIB_BUILD_MINIZIP) set(WORK_DIR ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/contrib/minizip/test/unzip_filename_termination.c b/contrib/minizip/test/unzip_filename_termination.c new file mode 100644 index 0000000000..40098e1aaa --- /dev/null +++ b/contrib/minizip/test/unzip_filename_termination.c @@ -0,0 +1,82 @@ +#include +#include + +#include "unzip.h" +#include "zip.h" + +int main(void) { + const char *archive_name = "minizip-filename-termination-test.zip"; + const char *long_name = "regression-filename-that-is-too-long.txt"; + const char expected_prefix[] = "regress"; + char filename[sizeof(expected_prefix)]; + zip_fileinfo file_info; + zipFile zip_file; + unzFile unzip_file; + int result = 1; + + memset(&file_info, 0, sizeof(file_info)); + remove(archive_name); + + zip_file = zipOpen(archive_name, APPEND_STATUS_CREATE); + if (zip_file == NULL) { + fprintf(stderr, "zipOpen failed\n"); + return result; + } + + if (zipOpenNewFileInZip(zip_file, long_name, &file_info, NULL, 0, NULL, + 0, NULL, 0, 0) != ZIP_OK) { + fprintf(stderr, "zipOpenNewFileInZip failed\n"); + zipClose(zip_file, NULL); + remove(archive_name); + return result; + } + + if (zipWriteInFileInZip(zip_file, "x", 1) != ZIP_OK) { + fprintf(stderr, "zipWriteInFileInZip failed\n"); + zipCloseFileInZip(zip_file); + zipClose(zip_file, NULL); + remove(archive_name); + return result; + } + + if (zipCloseFileInZip(zip_file) != ZIP_OK || + zipClose(zip_file, NULL) != ZIP_OK) { + fprintf(stderr, "zip close failed\n"); + remove(archive_name); + return result; + } + + unzip_file = unzOpen(archive_name); + if (unzip_file == NULL) { + fprintf(stderr, "unzOpen failed\n"); + remove(archive_name); + return result; + } + + memset(filename, 0xa5, sizeof(filename)); + if (unzGetCurrentFileInfo64(unzip_file, NULL, filename, sizeof(filename), + NULL, 0, NULL, 0) != UNZ_OK) { + fprintf(stderr, "unzGetCurrentFileInfo64 failed\n"); + unzClose(unzip_file); + remove(archive_name); + return result; + } + + if (memcmp(filename, expected_prefix, sizeof(expected_prefix) - 1) != 0 || + filename[sizeof(filename) - 1] != '\0') { + fprintf(stderr, "truncated filename was not NUL-terminated\n"); + unzClose(unzip_file); + remove(archive_name); + return result; + } + + if (unzClose(unzip_file) != UNZ_OK) { + fprintf(stderr, "unzClose failed\n"); + remove(archive_name); + return result; + } + + remove(archive_name); + result = 0; + return result; +}