0

When trying to unzip an image file using libzip, I have run across the issue where in the image data, I hit a null byte and libzip zip_fread sees this as EOF and stops reading the file, resulting in a corrupted image. What is the best way to get handle the null byte when reading an image and extract the full image?

To clarify, text only files extract perfectly fine.

Below is the code used:

int FileHandler::ExtractFiles(std::string& path, std::string& file, bool is_test)
{
    int err = 0;
    std::string fullPath = path + "\\" + file;
    zip* za = zip_open(fullPath.c_str(), 0, &err);
    struct zip_stat st;
    zip_stat_init(&st);
    int number_of_entries = zip_get_num_entries(za, NULL);
    for (zip_uint64_t i = 0; i < number_of_entries; ++i)
    {
        const char* name = zip_get_name(za, i, NULL);
        std::string s_name = name;
        size_t pos;
        std::string backsl = "\\";
        while ((pos = s_name.find(47)) != std::string::npos)
        {
            s_name.replace(pos, 1, backsl);
        }
        std::string fullFilePath = path + "\\" + s_name;
        if(!is_test)
            printf("Extracting: %s...\n", s_name.c_str());
        std::string fullDir;
        size_t found;
        found = fullFilePath.find_last_of("\\");
        if (found != std::string::npos)
        {
            fullDir = fullFilePath.substr(0, found);
        }
        struct zip_stat ist;
        zip_stat_init(&ist);
        zip_stat(za, name, 0, &ist);
        char* contents = new char[ist.size];
        zip_file* f = zip_fopen(za, name, 0);

        // zip_fread to contents buffer

        zip_fread(f, contents, ist.size);


        if (CreateDirectory(fullDir.c_str(), NULL) || ERROR_ALREADY_EXISTS == GetLastError())
        {

            // writing buffer to file

            if (!std::ofstream(fullFilePath).write(contents, ist.size))
            {
                return EXIT_FAILURE;
            }
        }
        zip_fclose(f);
    }
    zip_close(za);
    return EXIT_SUCCESS;
}
Kevin
  • 1

1 Answers1

0

gerum was able to point me in the right direction. For anyone that is wondering or has the same issue, I had to open the ofstream in binary mode and that resolved the issue.

Original code:

 // writing buffer to file

            if (!std::ofstream(fullFilePath).write(contents, ist.size))
            {
                return EXIT_FAILURE;
            }

Solution:

 // writing buffer to file

            if (!std::ofstream(fullFilePath, std::ios::binary).write(contents, ist.size))
            {
                return EXIT_FAILURE;
            }
Kevin
  • 1