From a7ffead8f62bbed151a5e8d89ae251b91e90e998 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Sun, 18 Sep 2016 15:20:27 -0400 Subject: [PATCH] fix more memory corruption --- libretro-common/file/archive_file.c | 49 +++++++--------- libretro-common/file/archive_file_7z.c | 2 +- libretro-common/file/archive_file_zlib.c | 63 +++++++++------------ libretro-common/include/file/archive_file.h | 37 ++++++++++-- tasks/task_database.c | 12 ++-- tasks/task_decompress.c | 37 +++++------- 6 files changed, 98 insertions(+), 102 deletions(-) diff --git a/libretro-common/file/archive_file.c b/libretro-common/file/archive_file.c index 52a4de13f6..0f19a40bc6 100644 --- a/libretro-common/file/archive_file.c +++ b/libretro-common/file/archive_file.c @@ -182,13 +182,11 @@ static int file_archive_get_file_list_cb( uint32_t csize, uint32_t size, uint32_t checksum, - void *userdata) + struct archive_extract_userdata *userdata) { union string_list_elem_attr attr; struct string_list *ext_list = NULL; const char *file_ext = NULL; - struct archive_extract_userdata *data = - (struct archive_extract_userdata*)userdata; size_t pathLen = strlen(path); (void)cdata; @@ -224,7 +222,7 @@ static int file_archive_get_file_list_cb( string_list_free(ext_list); } - return string_list_append(data->list, path, attr); + return string_list_append(userdata->list, path, attr); error: string_list_free(ext_list); @@ -234,28 +232,26 @@ error: static int file_archive_extract_cb(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t checksum, void *userdata) + uint32_t checksum, struct archive_extract_userdata *userdata) { const char *ext = path_get_extension(name); - struct archive_extract_userdata *data = (struct archive_extract_userdata*) - userdata; /* Extract first file that matches our list. */ - if (ext && string_list_find_elem(data->ext, ext)) + if (ext && string_list_find_elem(userdata->ext, ext)) { char new_path[PATH_MAX_LENGTH] = {0}; - if (data->extraction_directory) - fill_pathname_join(new_path, data->extraction_directory, + if (userdata->extraction_directory) + fill_pathname_join(new_path, userdata->extraction_directory, path_basename(name), sizeof(new_path)); else - fill_pathname_resolve_relative(new_path, data->archive_path, + fill_pathname_resolve_relative(new_path, userdata->archive_path, path_basename(name), sizeof(new_path)); - data->first_extracted_file_path = strdup(new_path); - data->found_file = file_archive_perform_mode(new_path, + userdata->first_extracted_file_path = strdup(new_path); + userdata->found_file = file_archive_perform_mode(new_path, valid_exts, cdata, cmode, csize, size, - 0, data); + 0, userdata); return 0; } @@ -361,7 +357,7 @@ int file_archive_parse_file_iterate( const char *file, const char *valid_exts, file_archive_file_cb file_cb, - void *userdata) + struct archive_extract_userdata *userdata) { if (!state) return -1; @@ -373,10 +369,8 @@ int file_archive_parse_file_iterate( case ARCHIVE_TRANSFER_INIT: if (file_archive_parse_file_init(state, file) == 0) { - struct archive_extract_userdata *data = - (struct archive_extract_userdata*)userdata; - if (data) - data->context = state->stream; + if (userdata) + userdata->context = state->stream; state->type = ARCHIVE_TRANSFER_ITERATE; } else @@ -384,7 +378,7 @@ int file_archive_parse_file_iterate( break; case ARCHIVE_TRANSFER_ITERATE: { - const struct file_archive_file_backend *backend = + const struct file_archive_file_backend *backend = file_archive_get_file_backend(file); if (backend) @@ -413,8 +407,6 @@ int file_archive_parse_file_iterate( } if (state->stream && state->backend) { - struct archive_extract_userdata *data = - (struct archive_extract_userdata*)userdata; state->backend->stream_free(state->stream); if (state->stream) @@ -422,8 +414,8 @@ int file_archive_parse_file_iterate( state->stream = NULL; - if (data) - data->context = NULL; + if (userdata) + userdata->context = NULL; } break; } @@ -449,7 +441,7 @@ int file_archive_parse_file_iterate( * Returns: true (1) on success, otherwise false (0). **/ static bool file_archive_parse_file(const char *file, const char *valid_exts, - file_archive_file_cb file_cb, void *userdata) + file_archive_file_cb file_cb, struct archive_extract_userdata *userdata) { file_archive_transfer_t state = {0}; bool returnerr = true; @@ -572,7 +564,7 @@ error: bool file_archive_perform_mode(const char *path, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t crc32, void *userdata) + uint32_t crc32, struct archive_extract_userdata *userdata) { switch (cmode) { @@ -585,10 +577,9 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts, { int ret = 0; file_archive_file_handle_t handle = {0}; - struct archive_extract_userdata *data = (struct archive_extract_userdata*)userdata; - handle.backend = file_archive_get_file_backend(data->archive_path); - handle.stream = data->context; + handle.backend = file_archive_get_file_backend(userdata->archive_path); + handle.stream = userdata->context; if (!handle.backend->stream_decompress_data_to_file_init(&handle, cdata, csize, size)) diff --git a/libretro-common/file/archive_file_7z.c b/libretro-common/file/archive_file_7z.c index c383653b80..d479f4e480 100644 --- a/libretro-common/file/archive_file_7z.c +++ b/libretro-common/file/archive_file_7z.c @@ -344,7 +344,7 @@ static int sevenzip_parse_file_iterate_step_internal( } static int sevenzip_parse_file_iterate_step(file_archive_transfer_t *state, - const char *valid_exts, void *userdata, file_archive_file_cb file_cb) + const char *valid_exts, struct archive_extract_userdata *userdata, file_archive_file_cb file_cb) { const uint8_t *cdata = NULL; uint32_t checksum = 0; diff --git a/libretro-common/file/archive_file_zlib.c b/libretro-common/file/archive_file_zlib.c index fd01d306d5..462b682174 100644 --- a/libretro-common/file/archive_file_zlib.c +++ b/libretro-common/file/archive_file_zlib.c @@ -208,15 +208,6 @@ static uint32_t zlib_stream_crc32_calculate(uint32_t crc, return encoding_crc32(crc, data, length); } -struct decomp_state -{ - char *opt_file; - char *needle; - void **buf; - size_t size; - bool found; -}; - static bool zip_file_decompressed_handle( file_archive_file_handle_t *handle, const uint8_t *cdata, uint32_t csize, @@ -270,10 +261,8 @@ static int zip_file_decompressed( const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t crc32, void *userdata) + uint32_t crc32, struct archive_extract_userdata *userdata) { - struct decomp_state *st = (struct decomp_state*)userdata; - /* Ignore directories. */ if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\') return 1; @@ -282,17 +271,17 @@ static int zip_file_decompressed( RARCH_LOG("[deflate] Path: %s, CRC32: 0x%x\n", name, crc32); #endif - if (strstr(name, st->needle)) + if (strstr(name, userdata->decomp_state.needle)) { bool goto_error = false; file_archive_file_handle_t handle = {0}; - st->found = true; + userdata->decomp_state.found = true; if (zip_file_decompressed_handle(&handle, cdata, csize, size, crc32)) { - if (st->opt_file != 0) + if (userdata->decomp_state.opt_file != 0) { /* Called in case core has need_fullpath enabled. */ char *buf = (char*)malloc(size); @@ -301,26 +290,26 @@ static int zip_file_decompressed( { /*RARCH_LOG("%s: %s\n", msg_hash_to_str(MSG_EXTRACTING_FILE), - st->opt_file);*/ + userdata->decomp_state.opt_file);*/ memcpy(buf, handle.data, size); - if (!filestream_write_file(st->opt_file, buf, size)) + if (!filestream_write_file(userdata->decomp_state.opt_file, buf, size)) goto_error = true; } free(buf); - st->size = 0; + userdata->decomp_state.size = 0; } else { /* Called in case core has need_fullpath disabled. * Will copy decompressed content directly into * RetroArch's ROM buffer. */ - *st->buf = malloc(size); - memcpy(*st->buf, handle.data, size); + *userdata->decomp_state.buf = malloc(size); + memcpy(*userdata->decomp_state.buf, handle.data, size); - st->size = size; + userdata->decomp_state.size = size; } } @@ -340,41 +329,41 @@ static int zip_file_read( const char *optional_outfile) { file_archive_transfer_t zlib; - struct decomp_state st; bool returnerr = true; int ret = 0; + struct archive_extract_userdata userdata = {0}; zlib.type = ARCHIVE_TRANSFER_INIT; - st.needle = NULL; - st.opt_file = NULL; - st.found = false; - st.buf = buf; + userdata.decomp_state.needle = NULL; + userdata.decomp_state.opt_file = NULL; + userdata.decomp_state.found = false; + userdata.decomp_state.buf = buf; if (needle) - st.needle = strdup(needle); + userdata.decomp_state.needle = strdup(needle); if (optional_outfile) - st.opt_file = strdup(optional_outfile); + userdata.decomp_state.opt_file = strdup(optional_outfile); do { ret = file_archive_parse_file_iterate(&zlib, &returnerr, path, - "", zip_file_decompressed, &st); + "", zip_file_decompressed, &userdata); if (!returnerr) break; - }while(ret == 0 && !st.found); + }while(ret == 0 && !userdata.decomp_state.found); file_archive_parse_file_iterate_stop(&zlib); - if (st.opt_file) - free(st.opt_file); - if (st.needle) - free(st.needle); + if (userdata.decomp_state.opt_file) + free(userdata.decomp_state.opt_file); + if (userdata.decomp_state.needle) + free(userdata.decomp_state.needle); - if (!st.found) + if (!userdata.decomp_state.found) return -1; - return st.size; + return userdata.decomp_state.size; } static int zip_parse_file_init(file_archive_transfer_t *state, @@ -442,7 +431,7 @@ static int zip_parse_file_iterate_step_internal( } static int zip_parse_file_iterate_step(file_archive_transfer_t *state, - const char *valid_exts, void *userdata, file_archive_file_cb file_cb) + const char *valid_exts, struct archive_extract_userdata *userdata, file_archive_file_cb file_cb) { const uint8_t *cdata = NULL; uint32_t checksum = 0; diff --git a/libretro-common/include/file/archive_file.h b/libretro-common/include/file/archive_file.h index 5c429b9b1c..7a752e12d8 100644 --- a/libretro-common/include/file/archive_file.h +++ b/libretro-common/include/file/archive_file.h @@ -25,9 +25,10 @@ #include #include - #include +#include + enum file_archive_transfer_type { ARCHIVE_TRANSFER_NONE = 0, @@ -63,6 +64,28 @@ enum file_archive_compression_mode ARCHIVE_MODE_COMPRESSED = 8 }; +struct decomp_state_t +{ + char *opt_file; + char *needle; + void **buf; + size_t size; + bool found; +}; + +typedef struct +{ + char *source_file; + char *subdir; + char *target_dir; + char *target_file; + char *valid_ext; + + char *callback_error; + + file_archive_transfer_t archive; +} decompress_state_t; + struct archive_extract_userdata { char *archive_path; @@ -73,12 +96,16 @@ struct archive_extract_userdata struct string_list *list; bool found_file; void *context; + char archive_name[PATH_MAX_LENGTH]; + uint32_t crc; + struct decomp_state_t decomp_state; + decompress_state_t dec; }; /* Returns true when parsing should continue. False to stop. */ typedef int (*file_archive_file_cb)(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t crc32, void *userdata); + uint32_t crc32, struct archive_extract_userdata *userdata); struct file_archive_file_backend { @@ -106,7 +133,7 @@ struct file_archive_file_backend int (*archive_parse_file_iterate_step)( file_archive_transfer_t *state, const char *valid_exts, - void *userdata, + struct archive_extract_userdata *userdata, file_archive_file_cb file_cb); const char *ident; }; @@ -117,7 +144,7 @@ int file_archive_parse_file_iterate( const char *file, const char *valid_exts, file_archive_file_cb file_cb, - void *userdata); + struct archive_extract_userdata *userdata); void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state); @@ -151,7 +178,7 @@ struct string_list* file_archive_get_file_list(const char *path, const char *val bool file_archive_perform_mode(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t crc32, void *userdata); + uint32_t crc32, struct archive_extract_userdata *userdata); void file_archive_deflate_init(void *data, int level); diff --git a/tasks/task_database.c b/tasks/task_database.c index 37c55b32de..3f91ca6b2e 100644 --- a/tasks/task_database.c +++ b/tasks/task_database.c @@ -66,13 +66,9 @@ typedef struct db_handle #ifdef HAVE_COMPRESSION static int archive_compare_crc32(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t crc32, void *userdata) + uint32_t crc32, struct archive_extract_userdata *userdata) { - database_state_handle_t *db_state = (database_state_handle_t*)userdata; - - db_state->crc = crc32; - - strlcpy(db_state->archive_name, name, sizeof(db_state->archive_name)); + userdata->crc = crc32; #if 0 RARCH_LOG("Going to compare CRC 0x%x for %s\n", crc32, name); @@ -418,6 +414,10 @@ static int task_database_iterate_playlist_archive( return task_database_iterate_crc_lookup( db_state, db, db_state->archive_name); + strlcpy(userdata.archive_name, db_state->archive_name, sizeof(userdata.archive_name)); + + userdata.crc = db_state->crc; + if (file_archive_parse_file_iterate(&db->state, &returnerr, name, NULL, archive_compare_crc32, &userdata)) diff --git a/tasks/task_decompress.c b/tasks/task_decompress.c index 9f150449e3..71c83213d1 100644 --- a/tasks/task_decompress.c +++ b/tasks/task_decompress.c @@ -25,24 +25,11 @@ #include "../verbosity.h" #include "../msg_hash.h" -typedef struct -{ - char *source_file; - char *subdir; - char *target_dir; - char *target_file; - char *valid_ext; - - char *callback_error; - - file_archive_transfer_t archive; -} decompress_state_t; - static int file_decompressed_target_file(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t crc32, void *userdata) + uint32_t crc32, struct archive_extract_userdata *userdata) { /* TODO/FIXME */ return 0; @@ -52,22 +39,21 @@ static int file_decompressed_subdir(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize,uint32_t size, - uint32_t crc32, void *userdata) + uint32_t crc32, struct archive_extract_userdata *userdata) { char path_dir[PATH_MAX_LENGTH] = {0}; char path[PATH_MAX_LENGTH] = {0}; - decompress_state_t *dec = (decompress_state_t*)userdata; /* Ignore directories. */ if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\') goto next_file; - if (strstr(name, dec->subdir) != name) + if (strstr(name, userdata->dec.subdir) != name) return 1; - name += strlen(dec->subdir) + 1; + name += strlen(userdata->dec.subdir) + 1; - fill_pathname_join(path, dec->target_dir, name, sizeof(path)); + fill_pathname_join(path, userdata->dec.target_dir, name, sizeof(path)); fill_pathname_basedir(path_dir, path, sizeof(path_dir)); /* Make directory */ @@ -84,8 +70,8 @@ next_file: return 1; error: - dec->callback_error = (char*)malloc(PATH_MAX_LENGTH); - snprintf(dec->callback_error, + userdata->dec.callback_error = (char*)malloc(PATH_MAX_LENGTH); + snprintf(userdata->dec.callback_error, PATH_MAX_LENGTH, "Failed to deflate %s.\n", path); return 0; @@ -93,10 +79,10 @@ error: static int file_decompressed(const char *name, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, - uint32_t crc32, void *userdata) + uint32_t crc32, struct archive_extract_userdata *userdata) { char path[PATH_MAX_LENGTH] = {0}; - decompress_state_t *dec = (decompress_state_t*)userdata; + decompress_state_t *dec = &userdata->dec; /* Ignore directories. */ if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\') @@ -180,9 +166,10 @@ static void task_decompress_handler_target_file(retro_task_t *task) { bool retdec; decompress_state_t *dec = (decompress_state_t*)task->state; + struct archive_extract_userdata userdata = {0}; int ret = file_archive_parse_file_iterate(&dec->archive, &retdec, dec->source_file, - dec->valid_ext, file_decompressed_target_file, dec); + dec->valid_ext, file_decompressed_target_file, &userdata); task->progress = file_archive_parse_file_progress(&dec->archive); @@ -201,6 +188,8 @@ static void task_decompress_handler_subdir(retro_task_t *task) decompress_state_t *dec = (decompress_state_t*)task->state; struct archive_extract_userdata userdata = {0}; + userdata.dec = *dec; + int ret = file_archive_parse_file_iterate(&dec->archive, &retdec, dec->source_file, dec->valid_ext, file_decompressed_subdir, &userdata);