nx_savedata: Ensure heap safety
This commit is contained in:
		| @@ -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; | ||||||
|   | |||||||
| @@ -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; | ||||||
| @@ -232,36 +237,64 @@ bool save_process(save_ctx_t *ctx) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void save_free_contexts(save_ctx_t *ctx) { | void save_free_contexts(save_ctx_t *ctx) { | ||||||
|  |     if (ctx->data_remap_storage.header) { | ||||||
|         for (unsigned int i = 0; i < ctx->data_remap_storage.header->map_segment_count; i++) { |         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[i].entries); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |     if (ctx->data_remap_storage.segments) | ||||||
|         free(ctx->data_remap_storage.segments); |         free(ctx->data_remap_storage.segments); | ||||||
|  |  | ||||||
|  |     if (ctx->meta_remap_storage.header) { | ||||||
|         for (unsigned int i = 0; i < ctx->meta_remap_storage.header->map_segment_count; i++) { |         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[i].entries); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |     if (ctx->meta_remap_storage.segments) | ||||||
|         free(ctx->meta_remap_storage.segments); |         free(ctx->meta_remap_storage.segments); | ||||||
|  |  | ||||||
|  |     if (ctx->data_remap_storage.map_entries) | ||||||
|         free(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); |         free(ctx->meta_remap_storage.map_entries); | ||||||
|  |  | ||||||
|     for (unsigned int i = 0; i < 2; i++) { |     for (unsigned int i = 0; i < 2; i++) { | ||||||
|  |         if (ctx->duplex_storage.layers[i].bitmap.bitmap) | ||||||
|             free(ctx->duplex_storage.layers[i].bitmap.bitmap); |             free(ctx->duplex_storage.layers[i].bitmap.bitmap); | ||||||
|  |         if (ctx->duplex_storage.layers[i].data_a.base_storage.ctx) | ||||||
|             free(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[i].data_b.base_storage.ctx); | ||||||
|     } |     } | ||||||
|  |     if (ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx) | ||||||
|         free(ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx); |         free(ctx->duplex_storage.layers[1].bitmap_storage.base_storage.ctx); | ||||||
|  |  | ||||||
|  |     if (ctx->journal_storage.map.map_storage) | ||||||
|         free(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); |         free(ctx->journal_storage.map.entries); | ||||||
|  |  | ||||||
|     for (unsigned int i = 0; i < 4; i++) { |     for (unsigned int i = 0; i < 4; i++) { | ||||||
|  |         if (ctx->core_data_ivfc_storage.integrity_storages[i].block_validities) | ||||||
|             free(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]); | ||||||
|     } |     } | ||||||
|  |     if (ctx->core_data_ivfc_storage.level_validities) | ||||||
|         free(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++) { | ||||||
|  |             if (ctx->fat_ivfc_storage.integrity_storages[i].block_validities) | ||||||
|                 free(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]); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     if (ctx->fat_ivfc_storage.level_validities) | ||||||
|         free(ctx->fat_ivfc_storage.level_validities); |         free(ctx->fat_ivfc_storage.level_validities); | ||||||
|  |  | ||||||
|  |     if (ctx->fat_storage) | ||||||
|         free(ctx->fat_storage); |         free(ctx->fat_storage); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user