aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2019-08-17 17:33:54 +0100
committerSimon Tatham <anakin@pobox.com>2022-07-31 08:53:08 +0100
commitcd338a1a35394a7abfd517569e908b54bf657aaa (patch)
treef61197d6f29f314440d035e7a41085bccc87934c
parent0dc46506ca85eb49299fc62a4362c8a4a655e320 (diff)
downloadpuzzles-cd338a1a35394a7abfd517569e908b54bf657aaa.zip
puzzles-cd338a1a35394a7abfd517569e908b54bf657aaa.tar.gz
puzzles-cd338a1a35394a7abfd517569e908b54bf657aaa.tar.bz2
puzzles-cd338a1a35394a7abfd517569e908b54bf657aaa.tar.xz
Unruly: Fix memory leak in dup_game()
The common structure is ref-counted and dup_game() bumps the reference count rather than copying it. However, blank_state() always allocates a new instance. Add a parameter to control whether blank_state() allocates it. Fixes: 47cec547e59a ("Unruly, Group: reference-count the 'immutable' array.")
-rw-r--r--unruly.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/unruly.c b/unruly.c
index 2ee4a69..174aceb 100644
--- a/unruly.c
+++ b/unruly.c
@@ -351,7 +351,7 @@ static const char *validate_desc(const game_params *params, const char *desc)
return NULL;
}
-static game_state *blank_state(int w2, int h2, bool unique)
+static game_state *blank_state(int w2, int h2, bool unique, bool new_common)
{
game_state *state = snew(game_state);
int s = w2 * h2;
@@ -360,12 +360,15 @@ static game_state *blank_state(int w2, int h2, bool unique)
state->h2 = h2;
state->unique = unique;
state->grid = snewn(s, char);
- state->common = snew(unruly_common);
- state->common->refcount = 1;
- state->common->immutable = snewn(s, bool);
+ if (new_common) {
+ state->common = snew(unruly_common);
+ state->common->refcount = 1;
+ state->common->immutable = snewn(s, bool);
+ }
memset(state->grid, EMPTY, s);
- memset(state->common->immutable, 0, s*sizeof(bool));
+ if (new_common)
+ memset(state->common->immutable, 0, s*sizeof(bool));
state->completed = state->cheated = false;
@@ -378,7 +381,7 @@ static game_state *new_game(midend *me, const game_params *params,
int w2 = params->w2, h2 = params->h2;
int s = w2 * h2;
- game_state *state = blank_state(w2, h2, params->unique);
+ game_state *state = blank_state(w2, h2, params->unique, true);
const char *p = desc;
int pos = 0;
@@ -415,7 +418,7 @@ static game_state *dup_game(const game_state *state)
int w2 = state->w2, h2 = state->h2;
int s = w2 * h2;
- game_state *ret = blank_state(w2, h2, state->unique);
+ game_state *ret = blank_state(w2, h2, state->unique, false);
memcpy(ret->grid, state->grid, s);
ret->common = state->common;
@@ -1372,7 +1375,7 @@ static char *new_game_desc(const game_params *params, random_state *rs,
while (true) {
attempts++;
- state = blank_state(w2, h2, params->unique);
+ state = blank_state(w2, h2, params->unique, true);
scratch = unruly_new_scratch(state);
if (unruly_fill_game(state, scratch, rs))
break;