fix more memory corruption

This commit is contained in:
Brad Parker 2016-09-18 15:20:27 -04:00
parent dc4760f5a6
commit a7ffead8f6
6 changed files with 98 additions and 102 deletions

View File

@ -182,13 +182,11 @@ static int file_archive_get_file_list_cb(
uint32_t csize, uint32_t csize,
uint32_t size, uint32_t size,
uint32_t checksum, uint32_t checksum,
void *userdata) struct archive_extract_userdata *userdata)
{ {
union string_list_elem_attr attr; union string_list_elem_attr attr;
struct string_list *ext_list = NULL; struct string_list *ext_list = NULL;
const char *file_ext = NULL; const char *file_ext = NULL;
struct archive_extract_userdata *data =
(struct archive_extract_userdata*)userdata;
size_t pathLen = strlen(path); size_t pathLen = strlen(path);
(void)cdata; (void)cdata;
@ -224,7 +222,7 @@ static int file_archive_get_file_list_cb(
string_list_free(ext_list); string_list_free(ext_list);
} }
return string_list_append(data->list, path, attr); return string_list_append(userdata->list, path, attr);
error: error:
string_list_free(ext_list); string_list_free(ext_list);
@ -234,28 +232,26 @@ error:
static int file_archive_extract_cb(const char *name, const char *valid_exts, static int file_archive_extract_cb(const char *name, const char *valid_exts,
const uint8_t *cdata, const uint8_t *cdata,
unsigned cmode, uint32_t csize, uint32_t size, 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); const char *ext = path_get_extension(name);
struct archive_extract_userdata *data = (struct archive_extract_userdata*)
userdata;
/* Extract first file that matches our list. */ /* 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}; char new_path[PATH_MAX_LENGTH] = {0};
if (data->extraction_directory) if (userdata->extraction_directory)
fill_pathname_join(new_path, data->extraction_directory, fill_pathname_join(new_path, userdata->extraction_directory,
path_basename(name), sizeof(new_path)); path_basename(name), sizeof(new_path));
else 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)); path_basename(name), sizeof(new_path));
data->first_extracted_file_path = strdup(new_path); userdata->first_extracted_file_path = strdup(new_path);
data->found_file = file_archive_perform_mode(new_path, userdata->found_file = file_archive_perform_mode(new_path,
valid_exts, cdata, cmode, csize, size, valid_exts, cdata, cmode, csize, size,
0, data); 0, userdata);
return 0; return 0;
} }
@ -361,7 +357,7 @@ int file_archive_parse_file_iterate(
const char *file, const char *file,
const char *valid_exts, const char *valid_exts,
file_archive_file_cb file_cb, file_archive_file_cb file_cb,
void *userdata) struct archive_extract_userdata *userdata)
{ {
if (!state) if (!state)
return -1; return -1;
@ -373,10 +369,8 @@ int file_archive_parse_file_iterate(
case ARCHIVE_TRANSFER_INIT: case ARCHIVE_TRANSFER_INIT:
if (file_archive_parse_file_init(state, file) == 0) if (file_archive_parse_file_init(state, file) == 0)
{ {
struct archive_extract_userdata *data = if (userdata)
(struct archive_extract_userdata*)userdata; userdata->context = state->stream;
if (data)
data->context = state->stream;
state->type = ARCHIVE_TRANSFER_ITERATE; state->type = ARCHIVE_TRANSFER_ITERATE;
} }
else else
@ -384,7 +378,7 @@ int file_archive_parse_file_iterate(
break; break;
case ARCHIVE_TRANSFER_ITERATE: case ARCHIVE_TRANSFER_ITERATE:
{ {
const struct file_archive_file_backend *backend = const struct file_archive_file_backend *backend =
file_archive_get_file_backend(file); file_archive_get_file_backend(file);
if (backend) if (backend)
@ -413,8 +407,6 @@ int file_archive_parse_file_iterate(
} }
if (state->stream && state->backend) if (state->stream && state->backend)
{ {
struct archive_extract_userdata *data =
(struct archive_extract_userdata*)userdata;
state->backend->stream_free(state->stream); state->backend->stream_free(state->stream);
if (state->stream) if (state->stream)
@ -422,8 +414,8 @@ int file_archive_parse_file_iterate(
state->stream = NULL; state->stream = NULL;
if (data) if (userdata)
data->context = NULL; userdata->context = NULL;
} }
break; break;
} }
@ -449,7 +441,7 @@ int file_archive_parse_file_iterate(
* Returns: true (1) on success, otherwise false (0). * Returns: true (1) on success, otherwise false (0).
**/ **/
static bool file_archive_parse_file(const char *file, const char *valid_exts, 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}; file_archive_transfer_t state = {0};
bool returnerr = true; bool returnerr = true;
@ -572,7 +564,7 @@ error:
bool file_archive_perform_mode(const char *path, const char *valid_exts, bool file_archive_perform_mode(const char *path, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, 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) switch (cmode)
{ {
@ -585,10 +577,9 @@ bool file_archive_perform_mode(const char *path, const char *valid_exts,
{ {
int ret = 0; int ret = 0;
file_archive_file_handle_t handle = {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.backend = file_archive_get_file_backend(userdata->archive_path);
handle.stream = data->context; handle.stream = userdata->context;
if (!handle.backend->stream_decompress_data_to_file_init(&handle, if (!handle.backend->stream_decompress_data_to_file_init(&handle,
cdata, csize, size)) cdata, csize, size))

View File

@ -344,7 +344,7 @@ static int sevenzip_parse_file_iterate_step_internal(
} }
static int sevenzip_parse_file_iterate_step(file_archive_transfer_t *state, 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; const uint8_t *cdata = NULL;
uint32_t checksum = 0; uint32_t checksum = 0;

View File

@ -208,15 +208,6 @@ static uint32_t zlib_stream_crc32_calculate(uint32_t crc,
return encoding_crc32(crc, data, length); 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( static bool zip_file_decompressed_handle(
file_archive_file_handle_t *handle, file_archive_file_handle_t *handle,
const uint8_t *cdata, uint32_t csize, const uint8_t *cdata, uint32_t csize,
@ -270,10 +261,8 @@ static int zip_file_decompressed(
const char *name, const char *valid_exts, const char *name, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, const uint8_t *cdata, unsigned cmode,
uint32_t csize, uint32_t size, 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. */ /* Ignore directories. */
if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\') if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\')
return 1; return 1;
@ -282,17 +271,17 @@ static int zip_file_decompressed(
RARCH_LOG("[deflate] Path: %s, CRC32: 0x%x\n", name, crc32); RARCH_LOG("[deflate] Path: %s, CRC32: 0x%x\n", name, crc32);
#endif #endif
if (strstr(name, st->needle)) if (strstr(name, userdata->decomp_state.needle))
{ {
bool goto_error = false; bool goto_error = false;
file_archive_file_handle_t handle = {0}; file_archive_file_handle_t handle = {0};
st->found = true; userdata->decomp_state.found = true;
if (zip_file_decompressed_handle(&handle, if (zip_file_decompressed_handle(&handle,
cdata, csize, size, crc32)) cdata, csize, size, crc32))
{ {
if (st->opt_file != 0) if (userdata->decomp_state.opt_file != 0)
{ {
/* Called in case core has need_fullpath enabled. */ /* Called in case core has need_fullpath enabled. */
char *buf = (char*)malloc(size); char *buf = (char*)malloc(size);
@ -301,26 +290,26 @@ static int zip_file_decompressed(
{ {
/*RARCH_LOG("%s: %s\n", /*RARCH_LOG("%s: %s\n",
msg_hash_to_str(MSG_EXTRACTING_FILE), msg_hash_to_str(MSG_EXTRACTING_FILE),
st->opt_file);*/ userdata->decomp_state.opt_file);*/
memcpy(buf, handle.data, size); 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; goto_error = true;
} }
free(buf); free(buf);
st->size = 0; userdata->decomp_state.size = 0;
} }
else else
{ {
/* Called in case core has need_fullpath disabled. /* Called in case core has need_fullpath disabled.
* Will copy decompressed content directly into * Will copy decompressed content directly into
* RetroArch's ROM buffer. */ * RetroArch's ROM buffer. */
*st->buf = malloc(size); *userdata->decomp_state.buf = malloc(size);
memcpy(*st->buf, handle.data, 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) const char *optional_outfile)
{ {
file_archive_transfer_t zlib; file_archive_transfer_t zlib;
struct decomp_state st;
bool returnerr = true; bool returnerr = true;
int ret = 0; int ret = 0;
struct archive_extract_userdata userdata = {0};
zlib.type = ARCHIVE_TRANSFER_INIT; zlib.type = ARCHIVE_TRANSFER_INIT;
st.needle = NULL; userdata.decomp_state.needle = NULL;
st.opt_file = NULL; userdata.decomp_state.opt_file = NULL;
st.found = false; userdata.decomp_state.found = false;
st.buf = buf; userdata.decomp_state.buf = buf;
if (needle) if (needle)
st.needle = strdup(needle); userdata.decomp_state.needle = strdup(needle);
if (optional_outfile) if (optional_outfile)
st.opt_file = strdup(optional_outfile); userdata.decomp_state.opt_file = strdup(optional_outfile);
do do
{ {
ret = file_archive_parse_file_iterate(&zlib, &returnerr, path, ret = file_archive_parse_file_iterate(&zlib, &returnerr, path,
"", zip_file_decompressed, &st); "", zip_file_decompressed, &userdata);
if (!returnerr) if (!returnerr)
break; break;
}while(ret == 0 && !st.found); }while(ret == 0 && !userdata.decomp_state.found);
file_archive_parse_file_iterate_stop(&zlib); file_archive_parse_file_iterate_stop(&zlib);
if (st.opt_file) if (userdata.decomp_state.opt_file)
free(st.opt_file); free(userdata.decomp_state.opt_file);
if (st.needle) if (userdata.decomp_state.needle)
free(st.needle); free(userdata.decomp_state.needle);
if (!st.found) if (!userdata.decomp_state.found)
return -1; return -1;
return st.size; return userdata.decomp_state.size;
} }
static int zip_parse_file_init(file_archive_transfer_t *state, 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, 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; const uint8_t *cdata = NULL;
uint32_t checksum = 0; uint32_t checksum = 0;

View File

@ -25,9 +25,10 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <boolean.h> #include <boolean.h>
#include <retro_miscellaneous.h>
enum file_archive_transfer_type enum file_archive_transfer_type
{ {
ARCHIVE_TRANSFER_NONE = 0, ARCHIVE_TRANSFER_NONE = 0,
@ -63,6 +64,28 @@ enum file_archive_compression_mode
ARCHIVE_MODE_COMPRESSED = 8 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 struct archive_extract_userdata
{ {
char *archive_path; char *archive_path;
@ -73,12 +96,16 @@ struct archive_extract_userdata
struct string_list *list; struct string_list *list;
bool found_file; bool found_file;
void *context; 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. */ /* Returns true when parsing should continue. False to stop. */
typedef int (*file_archive_file_cb)(const char *name, const char *valid_exts, 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, 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 struct file_archive_file_backend
{ {
@ -106,7 +133,7 @@ struct file_archive_file_backend
int (*archive_parse_file_iterate_step)( int (*archive_parse_file_iterate_step)(
file_archive_transfer_t *state, file_archive_transfer_t *state,
const char *valid_exts, const char *valid_exts,
void *userdata, struct archive_extract_userdata *userdata,
file_archive_file_cb file_cb); file_archive_file_cb file_cb);
const char *ident; const char *ident;
}; };
@ -117,7 +144,7 @@ int file_archive_parse_file_iterate(
const char *file, const char *file,
const char *valid_exts, const char *valid_exts,
file_archive_file_cb file_cb, 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); 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, bool file_archive_perform_mode(const char *name, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, 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); void file_archive_deflate_init(void *data, int level);

View File

@ -66,13 +66,9 @@ typedef struct db_handle
#ifdef HAVE_COMPRESSION #ifdef HAVE_COMPRESSION
static int archive_compare_crc32(const char *name, const char *valid_exts, static int archive_compare_crc32(const char *name, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, 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; userdata->crc = crc32;
db_state->crc = crc32;
strlcpy(db_state->archive_name, name, sizeof(db_state->archive_name));
#if 0 #if 0
RARCH_LOG("Going to compare CRC 0x%x for %s\n", crc32, name); 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( return task_database_iterate_crc_lookup(
db_state, db, db_state->archive_name); 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, if (file_archive_parse_file_iterate(&db->state,
&returnerr, name, NULL, archive_compare_crc32, &returnerr, name, NULL, archive_compare_crc32,
&userdata)) &userdata))

View File

@ -25,24 +25,11 @@
#include "../verbosity.h" #include "../verbosity.h"
#include "../msg_hash.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, static int file_decompressed_target_file(const char *name,
const char *valid_exts, const char *valid_exts,
const uint8_t *cdata, const uint8_t *cdata,
unsigned cmode, uint32_t csize, uint32_t size, unsigned cmode, uint32_t csize, uint32_t size,
uint32_t crc32, void *userdata) uint32_t crc32, struct archive_extract_userdata *userdata)
{ {
/* TODO/FIXME */ /* TODO/FIXME */
return 0; return 0;
@ -52,22 +39,21 @@ static int file_decompressed_subdir(const char *name,
const char *valid_exts, const char *valid_exts,
const uint8_t *cdata, const uint8_t *cdata,
unsigned cmode, uint32_t csize,uint32_t size, 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_dir[PATH_MAX_LENGTH] = {0};
char path[PATH_MAX_LENGTH] = {0}; char path[PATH_MAX_LENGTH] = {0};
decompress_state_t *dec = (decompress_state_t*)userdata;
/* Ignore directories. */ /* Ignore directories. */
if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\') if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\')
goto next_file; goto next_file;
if (strstr(name, dec->subdir) != name) if (strstr(name, userdata->dec.subdir) != name)
return 1; 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)); fill_pathname_basedir(path_dir, path, sizeof(path_dir));
/* Make directory */ /* Make directory */
@ -84,8 +70,8 @@ next_file:
return 1; return 1;
error: error:
dec->callback_error = (char*)malloc(PATH_MAX_LENGTH); userdata->dec.callback_error = (char*)malloc(PATH_MAX_LENGTH);
snprintf(dec->callback_error, snprintf(userdata->dec.callback_error,
PATH_MAX_LENGTH, "Failed to deflate %s.\n", path); PATH_MAX_LENGTH, "Failed to deflate %s.\n", path);
return 0; return 0;
@ -93,10 +79,10 @@ error:
static int file_decompressed(const char *name, const char *valid_exts, static int file_decompressed(const char *name, const char *valid_exts,
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, 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}; char path[PATH_MAX_LENGTH] = {0};
decompress_state_t *dec = (decompress_state_t*)userdata; decompress_state_t *dec = &userdata->dec;
/* Ignore directories. */ /* Ignore directories. */
if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\') 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; bool retdec;
decompress_state_t *dec = (decompress_state_t*)task->state; decompress_state_t *dec = (decompress_state_t*)task->state;
struct archive_extract_userdata userdata = {0};
int ret = file_archive_parse_file_iterate(&dec->archive, int ret = file_archive_parse_file_iterate(&dec->archive,
&retdec, dec->source_file, &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); 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; decompress_state_t *dec = (decompress_state_t*)task->state;
struct archive_extract_userdata userdata = {0}; struct archive_extract_userdata userdata = {0};
userdata.dec = *dec;
int ret = file_archive_parse_file_iterate(&dec->archive, int ret = file_archive_parse_file_iterate(&dec->archive,
&retdec, dec->source_file, &retdec, dec->source_file,
dec->valid_ext, file_decompressed_subdir, &userdata); dec->valid_ext, file_decompressed_subdir, &userdata);