shithub: puzzles

Download patch

ref: cd338a1a35394a7abfd517569e908b54bf657aaa
parent: 0dc46506ca85eb49299fc62a4362c8a4a655e320
author: Ben Hutchings <ben@decadent.org.uk>
date: Sat Aug 17 13:33:54 EDT 2019

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.")

--- a/unruly.c
+++ b/unruly.c
@@ -351,7 +351,7 @@
     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 @@
     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 @@
     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 @@
     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 @@
 
         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;