mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-10 00:08:23 +03:00
Fix major memory leak in ADVSceneKeeper
The VM can under no circumstance store it's own data on the heap. Doing so causes said data to leak into saved VM images. This is the worst kind of memory leak: even restarting the game will not fix it, because the data is permanently leaked into the save files. This will break save compatibility in games that use ADVSceneKeeper (e.g. Alice 2010 games).
This commit is contained in:
+25
-11
@@ -19,6 +19,7 @@
|
||||
#include "system4/utfsjis.h"
|
||||
|
||||
#include "vm/page.h"
|
||||
#include "xsystem4.h"
|
||||
|
||||
#include "AnteaterADVEngine.h"
|
||||
#include "iarray.h"
|
||||
@@ -309,7 +310,14 @@ bool ADVSceneKeeper_AddADVScene(struct page **page)
|
||||
return false;
|
||||
}
|
||||
scenes.data = xrealloc_array(scenes.data, scenes.n, scenes.n+1, sizeof(struct page*));
|
||||
scenes.data[scenes.n++] = copy_page(*page);
|
||||
|
||||
// serialize
|
||||
struct iarray_writer out;
|
||||
iarray_init_writer(&out, "SCN");
|
||||
iarray_write_struct(&out, *page);
|
||||
scenes.data[scenes.n++] = iarray_to_page(&out);
|
||||
iarray_free_writer(&out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -323,19 +331,23 @@ bool ADVSceneKeeper_GetADVScene(int index, struct page **page)
|
||||
if (index < 0 || (unsigned)index >= scenes.n)
|
||||
return false;
|
||||
|
||||
// deserialize
|
||||
struct iarray_reader in;
|
||||
if (!iarray_init_reader(&in, scenes.data[index], "SCN"))
|
||||
return false;
|
||||
|
||||
if (*page) {
|
||||
delete_page_vars(*page);
|
||||
free_page(*page);
|
||||
}
|
||||
|
||||
*page = copy_page(scenes.data[index]);
|
||||
return true;
|
||||
*page = iarray_read_struct(&in, scene_struct_no());
|
||||
return !in.error;
|
||||
}
|
||||
|
||||
void ADVSceneKeeper_Clear(void)
|
||||
{
|
||||
for (unsigned i = 0; i < scenes.n; i++) {
|
||||
delete_page_vars(scenes.data[i]);
|
||||
free_page(scenes.data[i]);
|
||||
}
|
||||
free(scenes.data);
|
||||
@@ -353,11 +365,11 @@ bool ADVSceneKeeper_Save(struct page **iarray)
|
||||
// this implementation just serializes whatever it's given. Note
|
||||
// also that the structure of 画面保管_t objects differs between games.
|
||||
struct iarray_writer w;
|
||||
iarray_init_writer(&w, "ADS");
|
||||
iarray_write(&w, 3); // version? Mankuchu puts 3 here
|
||||
iarray_init_writer(&w, "SCS");
|
||||
iarray_write(&w, 0); // version
|
||||
iarray_write(&w, scenes.n);
|
||||
for (unsigned i = 0; i < scenes.n; i++) {
|
||||
iarray_write_struct(&w, scenes.data[i]);
|
||||
iarray_write_array(&w, scenes.data[i]);
|
||||
}
|
||||
*iarray = iarray_to_page(&w);
|
||||
iarray_free_writer(&w);
|
||||
@@ -372,10 +384,12 @@ bool ADVSceneKeeper_Load(struct page **iarray)
|
||||
ADVSceneKeeper_Clear();
|
||||
|
||||
struct iarray_reader r;
|
||||
iarray_init_reader(&r, *iarray, "ADS");
|
||||
iarray_init_reader(&r, *iarray, "SCS");
|
||||
|
||||
if (iarray_read(&r) != 3)
|
||||
if (iarray_read(&r) != 0) {
|
||||
WARNING("Unsupported version of ADVSceneKeeper 'SCS' data");
|
||||
goto error;
|
||||
}
|
||||
|
||||
int nr_scenes = iarray_read(&r);
|
||||
if (nr_scenes < 0 || nr_scenes > 10000)
|
||||
@@ -384,9 +398,9 @@ bool ADVSceneKeeper_Load(struct page **iarray)
|
||||
scenes.n = 0;
|
||||
scenes.data = xcalloc(nr_scenes, sizeof(struct page*));
|
||||
|
||||
int struct_type = scene_struct_no();
|
||||
for (int i = 0; i < nr_scenes; i++) {
|
||||
scenes.data[scenes.n++] = iarray_read_struct(&r, struct_type);
|
||||
struct ain_type type = { .data = AIN_ARRAY_INT, .struc = 0, .rank = 0 };
|
||||
scenes.data[scenes.n++] = iarray_read_array(&r, &type);
|
||||
if (r.error)
|
||||
goto error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user