nx_savedata: Ensure heap safety

This commit is contained in:
shchmue 2020-12-09 19:06:46 -07:00
parent 1b5a7bb302
commit 1e87828db4
4 changed files with 59 additions and 28 deletions

View file

@ -102,7 +102,7 @@ uint32_t save_remap_storage_read(remap_storage_ctx_t *ctx, void *buffer, uint64_
} }
uint64_t in_pos = offset; uint64_t in_pos = offset;
uint32_t out_pos = 0; uint32_t out_pos = 0;
uint32_t remaining = count; uint32_t remaining = (u32)count;
while (remaining) { while (remaining) {
uint64_t entry_pos = in_pos - entry->entry.virtual_offset; uint64_t entry_pos = in_pos - entry->entry.virtual_offset;
@ -135,7 +135,7 @@ uint32_t save_remap_storage_write(remap_storage_ctx_t *ctx, const void *buffer,
} }
uint64_t in_pos = offset; uint64_t in_pos = offset;
uint32_t out_pos = 0; uint32_t out_pos = 0;
uint32_t remaining = count; uint32_t remaining = (u32)count;
while (remaining) { while (remaining) {
uint64_t entry_pos = in_pos - entry->entry.virtual_offset; uint64_t entry_pos = in_pos - entry->entry.virtual_offset;

View file

@ -143,6 +143,11 @@ bool save_process(save_ctx_t *ctx) {
} }
} }
if (ctx->header.layout.version > VERSION_DISF_5) {
EPRINTF("Unsupported save version.\nLibrary must be updated.");
return false;
}
/* Initialize remap storages. */ /* Initialize remap storages. */
ctx->data_remap_storage.header = &ctx->header.main_remap_header; ctx->data_remap_storage.header = &ctx->header.main_remap_header;
ctx->meta_remap_storage.header = &ctx->header.meta_remap_header; ctx->meta_remap_storage.header = &ctx->header.meta_remap_header;
@ -177,7 +182,7 @@ bool save_process(save_ctx_t *ctx) {
return false; return false;
} }
/* Initialize meta remap storage. */ /* Initialize meta remap storage. */
substorage_init(&ctx->meta_remap_storage.base_storage, &hierarchical_duplex_storage_vt, &ctx->duplex_storage, 0, ctx->duplex_storage.data_layer->_length); substorage_init(&ctx->meta_remap_storage.base_storage, &hierarchical_duplex_storage_vt, &ctx->duplex_storage, 0, ctx->duplex_storage.data_layer->_length);
ctx->meta_remap_storage.map_entries = calloc(1, sizeof(remap_entry_ctx_t) * ctx->meta_remap_storage.header->map_entry_count); ctx->meta_remap_storage.map_entries = calloc(1, sizeof(remap_entry_ctx_t) * ctx->meta_remap_storage.header->map_entry_count);
if (substorage_read(&ctx->base_storage, remap_buffer, ctx->header.layout.meta_map_entry_offset, meta_remap_entry_size) != meta_remap_entry_size) { if (substorage_read(&ctx->base_storage, remap_buffer, ctx->header.layout.meta_map_entry_offset, meta_remap_entry_size) != meta_remap_entry_size) {
@ -232,37 +237,65 @@ bool save_process(save_ctx_t *ctx) {
} }
void save_free_contexts(save_ctx_t *ctx) { void save_free_contexts(save_ctx_t *ctx) {
for (unsigned int i = 0; i < ctx->data_remap_storage.header->map_segment_count; i++) { if (ctx->data_remap_storage.header) {
free(ctx->data_remap_storage.segments[i].entries); for (unsigned int i = 0; i < ctx->data_remap_storage.header->map_segment_count; i++) {
if (ctx->data_remap_storage.segments && ctx->data_remap_storage.segments[i].entries)
free(ctx->data_remap_storage.segments[i].entries);
}
} }
free(ctx->data_remap_storage.segments); if (ctx->data_remap_storage.segments)
for (unsigned int i = 0; i < ctx->meta_remap_storage.header->map_segment_count; i++) { free(ctx->data_remap_storage.segments);
free(ctx->meta_remap_storage.segments[i].entries);
if (ctx->meta_remap_storage.header) {
for (unsigned int i = 0; i < ctx->meta_remap_storage.header->map_segment_count; i++) {
if (ctx->meta_remap_storage.segments && ctx->meta_remap_storage.segments[i].entries)
free(ctx->meta_remap_storage.segments[i].entries);
}
} }
free(ctx->meta_remap_storage.segments); if (ctx->meta_remap_storage.segments)
free(ctx->data_remap_storage.map_entries); free(ctx->meta_remap_storage.segments);
free(ctx->meta_remap_storage.map_entries);
if (ctx->data_remap_storage.map_entries)
free(ctx->data_remap_storage.map_entries);
if (ctx->meta_remap_storage.map_entries)
free(ctx->meta_remap_storage.map_entries);
for (unsigned int i = 0; i < 2; i++) { for (unsigned int i = 0; i < 2; i++) {
free(ctx->duplex_storage.layers[i].bitmap.bitmap); if (ctx->duplex_storage.layers[i].bitmap.bitmap)
free(ctx->duplex_storage.layers[i].data_a.base_storage.ctx); free(ctx->duplex_storage.layers[i].bitmap.bitmap);
free(ctx->duplex_storage.layers[i].data_b.base_storage.ctx); if (ctx->duplex_storage.layers[i].data_a.base_storage.ctx)
free(ctx->duplex_storage.layers[i].data_a.base_storage.ctx);
if (ctx->duplex_storage.layers[i].data_b.base_storage.ctx)
free(ctx->duplex_storage.layers[i].data_b.base_storage.ctx);
} }
free(ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx); if (ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx)
free(ctx->journal_storage.map.map_storage); free(ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx);
free(ctx->journal_storage.map.entries);
if (ctx->journal_storage.map.map_storage)
free(ctx->journal_storage.map.map_storage);
if (ctx->journal_storage.map.entries)
free(ctx->journal_storage.map.entries);
for (unsigned int i = 0; i < 4; i++) { for (unsigned int i = 0; i < 4; i++) {
free(ctx->core_data_ivfc_storage.integrity_storages[i].block_validities); if (ctx->core_data_ivfc_storage.integrity_storages[i].block_validities)
free(ctx->core_data_ivfc_storage.integrity_storages[i].block_validities);
save_cached_storage_finalize(&ctx->core_data_ivfc_storage.levels[i + 1]); save_cached_storage_finalize(&ctx->core_data_ivfc_storage.levels[i + 1]);
} }
free(ctx->core_data_ivfc_storage.level_validities); if (ctx->core_data_ivfc_storage.level_validities)
free(ctx->core_data_ivfc_storage.level_validities);
if (ctx->header.layout.version >= VERSION_DISF_5) { if (ctx->header.layout.version >= VERSION_DISF_5) {
for (unsigned int i = 0; i < 3; i++) { for (unsigned int i = 0; i < 3; i++) {
free(ctx->fat_ivfc_storage.integrity_storages[i].block_validities); if (ctx->fat_ivfc_storage.integrity_storages[i].block_validities)
free(ctx->fat_ivfc_storage.integrity_storages[i].block_validities);
save_cached_storage_finalize(&ctx->fat_ivfc_storage.levels[i + 1]); save_cached_storage_finalize(&ctx->fat_ivfc_storage.levels[i + 1]);
} }
} }
free(ctx->fat_ivfc_storage.level_validities); if (ctx->fat_ivfc_storage.level_validities)
free(ctx->fat_storage); free(ctx->fat_ivfc_storage.level_validities);
if (ctx->fat_storage)
free(ctx->fat_storage);
} }
static ALWAYS_INLINE bool save_flush(save_ctx_t *ctx) { static ALWAYS_INLINE bool save_flush(save_ctx_t *ctx) {

View file

@ -45,11 +45,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <string.h> #include <string.h>
void storage_init(storage *this, const storage_vt *vt, void *ctx) {
this->vt = vt;
this->ctx = ctx;
}
void substorage_init(substorage *this, const storage_vt *vt, void *ctx, uint64_t offset, uint64_t length) { void substorage_init(substorage *this, const storage_vt *vt, void *ctx, uint64_t offset, uint64_t length) {
storage_init(&this->base_storage, vt, ctx); storage_init(&this->base_storage, vt, ctx);
this->offset = offset; this->offset = offset;

View file

@ -51,7 +51,10 @@ typedef struct {
void *ctx; void *ctx;
} storage; } storage;
void storage_init(storage *this, const storage_vt *vt, void *ctx); static void ALWAYS_INLINE storage_init(storage *this, const storage_vt *vt, void *ctx) {
this->vt = vt;
this->ctx = ctx;
}
typedef struct { typedef struct {
uint64_t offset; uint64_t offset;