Fix memory corruption through InitString and second-engine loading
authorH.G. Muller <h.g.muller@hccnet.nl>
Wed, 4 Apr 2012 10:18:43 +0000 (12:18 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Tue, 10 Apr 2012 09:27:57 +0000 (11:27 +0200)
The InitString and ComputerString options were not swapped when replacing
the second engine, so that the ChessProgramStates of the first engine
could point to an invalid (already freed) init string. Also make sure
that appData.directory contains its value in allocated memory, even
when hand-loading engines.
  Some of the rare options were not swapped either, and would thus
always be loaded for the first engine when -singleEngineList was true.
They are now also all reset to their default, before engine load,
to prevent options of one engine to linger on for a next that does
not specify them. The intentional exception is -firstHost.

args.h
backend.c

diff --git a/args.h b/args.h
index b29daa7..a72e95a 100644 (file)
--- a/args.h
+++ b/args.h
@@ -616,8 +616,8 @@ ArgDescriptor argDescriptors[] = {
   { "smpCores", ArgInt, (void *) &appData.smpCores, TRUE, (ArgIniType) 1 },
   { "egtFormats", ArgString, (void *) &appData.egtFormats, TRUE, (ArgIniType) "" },
   { "niceEngines", ArgInt, (void *) &appData.niceEngines, TRUE, INVALID },
-  { "firstLogo", ArgFilename, (void *) &appData.firstLogo, FALSE, INVALID },
-  { "secondLogo", ArgFilename, (void *) &appData.secondLogo, FALSE, INVALID },
+  { "firstLogo", ArgFilename, (void *) &appData.firstLogo, FALSE, (ArgIniType) "" },
+  { "secondLogo", ArgFilename, (void *) &appData.secondLogo, FALSE, (ArgIniType) "" },
   { "autoLogo", ArgBoolean, (void *) &appData.autoLogo, TRUE, INVALID },
   { "firstOptions", ArgString, (void *) &appData.firstOptions, FALSE, (ArgIniType) "" },
   { "secondOptions", ArgString, (void *) &appData.secondOptions, FALSE, (ArgIniType) "" },
index 3d65707..6772a97 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -876,7 +876,8 @@ extern Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick;
 static char resetOptions[] = 
        "-reuse -firstIsUCI false -firstHasOwnBookUCI true -firstTimeOdds 1 "
        "-firstInitString \"" INIT_STRING "\" -firstComputerString \"" COMPUTER_STRING "\" "
-       "-firstOptions \"\" -firstNPS -1 -fn \"\"";
+       "-firstFeatures \"\" -firstLogo \"\" -firstAccumulateTC 1 "
+       "-firstOptions \"\" -firstNPS -1 -fn \"\" -firstScoreAbs false";
 
 void
 FloatToFront(char **list, char *engineLine)
@@ -904,7 +905,8 @@ Load (ChessProgramState *cps, int i)
     if(engineLine && engineLine[0]) { // an engine was selected from the combo box
        snprintf(buf, MSG_SIZ, "-fcp %s", engineLine);
        SwapEngines(i); // kludge to parse -f* / -first* like it is -s* / -second*
-       ParseArgsFromString(resetOptions); appData.fenOverride[0] = NULL; appData.pvSAN[0] = FALSE;
+       ParseArgsFromString(resetOptions); appData.pvSAN[0] = FALSE;
+       FREE(appData.fenOverride[0]); appData.fenOverride[0] = NULL;
        appData.firstProtocolVersion = PROTOVER;
        ParseArgsFromString(buf);
        SwapEngines(i);
@@ -915,20 +917,20 @@ Load (ChessProgramState *cps, int i)
     p = engineName;
     while(q = strchr(p, SLASH)) p = q+1;
     if(*p== NULLCHAR) { DisplayError(_("You did not specify the engine executable"), 0); return; }
-    if(engineDir[0] != NULLCHAR)
-       appData.directory[i] = engineDir;
-    else if(p != engineName) { // derive directory from engine path, when not given
+    if(engineDir[0] != NULLCHAR) {
+       ASSIGN(appData.directory[i], engineDir);
+    } else if(p != engineName) { // derive directory from engine path, when not given
        p[-1] = 0;
-       appData.directory[i] = strdup(engineName);
+       ASSIGN(appData.directory[i], engineName);
        p[-1] = SLASH;
        if(SLASH == '/' && p - engineName > 1) *(p -= 2) = '.'; // for XBoard use ./exeName as command after split!
-    } else appData.directory[i] = ".";
+    } else { ASSIGN(appData.directory[i], "."); }
     if(params[0]) {
        if(strchr(p, ' ') && !strchr(p, '"')) snprintf(buf2, MSG_SIZ, "\"%s\"", p), p = buf2; // quote if it contains spaces
        snprintf(command, MSG_SIZ, "%s %s", p, params);
        p = command;
     }
-    appData.chessProgram[i] = strdup(p);
+    ASSIGN(appData.chessProgram[i], p);
     appData.isUCI[i] = isUCI;
     appData.protocolVersion[i] = v1 ? 1 : PROTOVER;
     appData.hasOwnBookUCI[i] = hasBook;
@@ -10077,6 +10079,13 @@ SwapEngines (int n)
     SWAP(pgnName, p)
     SWAP(pvSAN, h)
     SWAP(engOptions, p)
+    SWAP(engInitString, p)
+    SWAP(computerString, p)
+    SWAP(features, p)
+    SWAP(fenOverride, p)
+    SWAP(NPS, h)
+    SWAP(accumulateTC, h)
+    SWAP(host, p)
 }
 
 int