Skip to content

unzReadCurrentFile() returning wrong content for ZIP64 file entry #279

@vszakats

Description

@vszakats

Self-contained example:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include "mz.h"
#include "mz_zip.h"
#include "mz_compat.h"

static void myextract(const char * zip, const char * fn)
{
    unz_file_info64 ufi;
    unzFile hUnzip;
    void * buffer;
    int iRead;
    int found;

    printf("uopen : %p\n", (void *)(hUnzip = unzOpen2_64(zip, NULL)));

    // find requested file
    printf("ufi1st: %d\n", unzGoToFirstFile(hUnzip));
    found = 0;
    for(;;)
    {
        char fnz[256];

        printf("ufinfo: %d\n", unzGetCurrentFileInfo64(hUnzip, &ufi, (char *)&fnz, sizeof(fnz) - 1, NULL, 0, NULL, 0));
        if(strcmp(fnz, fn) == 0)
        {
            printf("FOUND!: %s\n", fn);
            printf("uoffst: %lld\n", unzGetOffset64(hUnzip));
            printf("ufopen: %d\n", unzOpenCurrentFile3(hUnzip, NULL, NULL, 0, NULL));
            buffer = malloc(ufi.uncompressed_size);
            printf("uread : %d\n", iRead = unzReadCurrentFile(hUnzip, buffer, ufi.uncompressed_size));
            printf("READ  : %s\n", buffer);  /* WITH ZIP64, IT'S RETURNING THE CONTENT OF THE FIRST FILE WHILE POSITIONED ON THE 2ND */
            free(buffer);
            printf("ufclos: %d\n", unzCloseCurrentFile(hUnzip));
            found = 1;
            break;
        }

        printf("ufinxt: %d\n", unzGoToNextFile(hUnzip));
    }

    if(found == 0)
        printf("not found: %s\n", fn);

    printf("uclose: %d\n", unzClose(hUnzip));
}

int main(void)
{
    int zip64;

    // create two .zip files, one regular and one with ZIP64 enabled, with two file entries each
    for(zip64 = 0; zip64 <= 1; zip64++)
    {
        static const unsigned char content1[] = "11.txt-first file";
        static const unsigned char content2[] = "22.txt-second file";

        zipFile hZip;
        zip_fileinfo zfi;

        printf("zcreat: %p\n", (void *)(hZip = zipOpen2_64(zip64 ? "test_64.zip" : "test_32.zip", APPEND_STATUS_CREATE, NULL, NULL)));
        memset(&zfi, 0, sizeof(zfi));
        printf("zaddfi: %d\n", zipOpenNewFileInZip4_64(hZip, "11.txt", &zfi, NULL, 0, NULL, 0, NULL,
                                                       MZ_COMPRESS_METHOD_DEFLATE, 6, 0,
                                                       -MAX_WBITS, DEF_MEM_LEVEL, 0,
                                                       NULL, 0xD7681E40 /* crc of 'content1' */,
                                                       0, 0, zip64));
        printf("zwrite: %d\n", zipWriteInFileInZip(hZip, content1, sizeof(content1)));
        printf("zfclos: %d\n", zipCloseFileInZip(hZip));
        printf("zaddfi: %d\n", zipOpenNewFileInZip4_64(hZip, "22.txt", &zfi, NULL, 0, NULL, 0, NULL,
                                                       MZ_COMPRESS_METHOD_DEFLATE, 6, 0,
                                                       -MAX_WBITS, DEF_MEM_LEVEL, 0,
                                                       NULL, 0x7A416084 /* crc of 'content2' */,
                                                       0, 0, zip64));
        printf("zwrite: %d\n", zipWriteInFileInZip(hZip, content2, sizeof(content2)));
        printf("zfclos: %d\n", zipCloseFileInZip(hZip));
        printf("zclose: %d\n", zipClose(hZip, NULL));
    }

    // try extracting the last (= second) file from each .zip
    myextract("test_32.zip", "22.txt");
    myextract("test_64.zip", "22.txt");

    return 0;
}

Expected result is that the content of the second file entry is shown for both files (in the READ : output line).
Actual result is that despite being positioned on the 2nd file, the content of the first file is being returned by unzReadCurrentFile(). After that, unzCloseCurrentFile() returns with -105.

Regular tools such as unzip and 7za are correctly reading the second file from both .zip files, which suggests that the issue is not with the generated file, but with the reading (unzip) logic of minizip.

Metadata

Metadata

Assignees

No one assigned

    Labels

    compatibilityBackwards compatibilityfixedIssue or bug has been fixedzipZIP file format

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions