1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Fix buffer over-read and memory leaks when using long filepaths in a zip archive and improved robustness of long filepaths and reading files.

This commit is contained in:
Mack
2022-12-06 17:40:46 +00:00
parent 83d5cbf519
commit 1326b7e04f
7 changed files with 110 additions and 45 deletions

View File

@@ -30,6 +30,48 @@
#include "zip_io.h"
#include "core/templates/local_vector.h"
int godot_unzip_get_current_file_info(unzFile p_zip_file, unz_file_info64 &r_file_info, String &r_filepath) {
const uLong short_file_path_buffer_size = 16384ul;
char short_file_path_buffer[short_file_path_buffer_size];
int err = unzGetCurrentFileInfo64(p_zip_file, &r_file_info, short_file_path_buffer, short_file_path_buffer_size, nullptr, 0, nullptr, 0);
if (unlikely((err != UNZ_OK) || (r_file_info.size_filename > short_file_path_buffer_size))) {
LocalVector<char> long_file_path_buffer;
long_file_path_buffer.resize(r_file_info.size_filename);
err = unzGetCurrentFileInfo64(p_zip_file, &r_file_info, long_file_path_buffer.ptr(), long_file_path_buffer.size(), nullptr, 0, nullptr, 0);
if (err != UNZ_OK) {
return err;
}
r_filepath = String::utf8(long_file_path_buffer.ptr(), r_file_info.size_filename);
} else {
r_filepath = String::utf8(short_file_path_buffer, r_file_info.size_filename);
}
return err;
}
int godot_unzip_locate_file(unzFile p_zip_file, String p_filepath, bool p_case_sensitive) {
int err = unzGoToFirstFile(p_zip_file);
while (err == UNZ_OK) {
unz_file_info64 current_file_info;
String current_filepath;
err = godot_unzip_get_current_file_info(p_zip_file, current_file_info, current_filepath);
if (err == UNZ_OK) {
bool filepaths_are_equal = p_case_sensitive ? (p_filepath == current_filepath) : (p_filepath.nocasecmp_to(current_filepath) == 0);
if (filepaths_are_equal) {
return UNZ_OK;
}
err = unzGoToNextFile(p_zip_file);
}
}
return err;
}
//
void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
Ref<FileAccess> *fa = reinterpret_cast<Ref<FileAccess> *>(opaque);
ERR_FAIL_COND_V(fa == nullptr, nullptr);
@@ -38,17 +80,17 @@ void *zipio_open(voidpf opaque, const char *p_fname, int mode) {
fname.parse_utf8(p_fname);
int file_access_mode = 0;
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
file_access_mode |= FileAccess::WRITE;
}
if (mode & ZLIB_FILEFUNC_MODE_READ) {
file_access_mode |= FileAccess::READ;
}
if (mode & ZLIB_FILEFUNC_MODE_WRITE) {
file_access_mode |= FileAccess::WRITE;
}
if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
file_access_mode |= FileAccess::WRITE_READ;
}
(*fa) = FileAccess::open(fname, file_access_mode);
(*fa) = FileAccess::open(fname, file_access_mode);
if (fa->is_null()) {
return nullptr;
}