From 641643a8970993204252074c597b2ebc631c7d71 Mon Sep 17 00:00:00 2001
From: onefang
Date: Sat, 16 May 2020 15:21:20 +1000
Subject: Fix the last of the known leaks.

---
 src/sledjchisl/sledjchisl.c | 115 ++++++++++++++++++++++++++++++--------------
 1 file changed, 78 insertions(+), 37 deletions(-)

(limited to 'src')

diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c
index ddb041d..02bebe6 100644
--- a/src/sledjchisl/sledjchisl.c
+++ b/src/sledjchisl/sledjchisl.c
@@ -845,6 +845,7 @@ int checkSimIsRunning(char *sim)
         }
       }
     }
+    free(pid);
   }
 
   // Now check if it's really really running.  lol
@@ -1845,18 +1846,20 @@ void dbPull(reqData *Rd, char *table, rowData *rows)
   qhashtbl_t *me = rows->rows->popfirst(rows->rows, NULL);
   qhashtbl_obj_t obj;
 
-  memset((void*)&obj, 0, sizeof(obj));
-  me->lock(me);
-  while(me->getnext(me, &obj, false) == true)
+  if (NULL != me)
   {
-    where = xmprintf("%s.%s", table, obj.name);
+    memset((void*)&obj, 0, sizeof(obj));
+    me->lock(me);
+    while(me->getnext(me, &obj, false) == true)
+    {
+      where = xmprintf("%s.%s", table, obj.name);
 d("dbPull(Rd->database) %s = %s", where, (char *) obj.data);
-    Rd->database->putstr(Rd->database, where, (char *) obj.data);
-//    me->remove(me, obj.name);
-    free(where);
+      Rd->database->putstr(Rd->database, where, (char *) obj.data);
+      free(where);
+    }
+    me->unlock(me);
+    me->free(me);
   }
-  me->unlock(me);
-  me->free(me);
   free(rows->fieldNames);
   rows->rows->free(rows->rows);
   free(rows);
@@ -2202,8 +2205,6 @@ gridStats *getStats(MYSQL *db, gridStats *stats)
       else
 	y = atoll(tmp);
       simSize += x * y;
-// TODO - I can't win.  valgrind complains that either something is being freed twice, or not freed at all, no matter what I do.
-//	    This seems to keep the memory loss down to a minimum.
       row->free(row);
       rows->rows->removefirst(rows->rows);
     }
@@ -2300,6 +2301,18 @@ struct _cookie
   enum cookieSame site;
 };
 
+void freeCookie(reqData *Rd, char *cki)
+{
+  cookie *ck0 = Rd->Rcookies->get(Rd->Rcookies, cki, NULL, false);
+
+  if (NULL != ck0)
+  {
+    if (NULL != ck0->value)
+      free(ck0->value);
+    Rd->Rcookies->remove(Rd->Rcookies, cki);
+  }
+}
+
 cookie *setCookie(reqData *Rd, char *cki, char *value)
 {
   cookie *ret = xzalloc(sizeof(cookie));
@@ -2308,6 +2321,7 @@ cookie *setCookie(reqData *Rd, char *cki, char *value)
 
   // Validate this, as there is a limited set of characters allowed.
   qstrreplace("tr", cook, "()<>@,;:\\\"/[]?={} \t", "_");
+  freeCookie(Rd, cook);
   l = strlen(cook);
   for (i = 0; i < l; i++)
   {
@@ -2316,9 +2330,9 @@ cookie *setCookie(reqData *Rd, char *cki, char *value)
   }
   l = strlen(value);
   if (0 != l)
-    ret->value = qurl_encode(value, l);		// LEAKY
+    ret->value = qurl_encode(value, l);
   else
-    ret->value = xstrdup("");			// LEAKY
+    ret->value = xstrdup("");
   ret->httpOnly = TRUE;
   ret->site = CS_STRICT;
   ret->secure = TRUE;
@@ -2331,16 +2345,6 @@ cookie *setCookie(reqData *Rd, char *cki, char *value)
   return ret;
 }
 
-void freeCookie(reqData *Rd, char *cki)
-{
-  cookie *ck0 = Rd->cookies->get(Rd->cookies, cki, NULL, false);
-
-// TODO - Crash or leak, there is no free.
-//  if ((NULL != ck0) && (NULL != ck0->value))
-//    free(ck0->value);
-  Rd->cookies->remove(Rd->cookies, cki);
-}
-
 char *getCookie(qhashtbl_t *cookies, char *cki)
 {
   char *ret = NULL;
@@ -3533,7 +3537,7 @@ t("Write shs %s", tnm4);
   {
 // TODO - Later use libcurl.
 
-      char *uuid = Rd->shs.UUID, *first = getStrH(Rd->stuff, "firstName"), *last = getStrH(Rd->stuff, "lastName");
+      char *first = getStrH(Rd->stuff, "firstName"), *last = getStrH(Rd->stuff, "lastName");
 // TODO - should be from Rd.shs->linky-hashish
       char *t0 = xstrdup(Rd->lnk->hashish), *content, *command;
 
@@ -3620,6 +3624,7 @@ static void generateAccountUUID(reqData *Rd)
     users = dbCount(Rd->db, "UserAccounts", where);
     free(where);
   } while (users != 0);
+  if (NULL != Rd->shs.UUID)	free(Rd->shs.UUID);
   Rd->shs.UUID = xstrdup(uuid);
   Rd->shs.level = -200;
   Rd->database->putstr(Rd->database, "UserAccounts.PrincipalID", uuid);
@@ -4113,7 +4118,7 @@ T("new sesh %s %s %s", linky ? "linky" : "session", ret->UUID, ret->name);
 	{
 	  uuid_clear(binuuid);
 	  uuid_unparse_lower(binuuid, uuid);
-	  ret->UUID = uuid;
+	  ret->UUID = xstrdup(uuid);
 	}
 	t0 = xmprintf("%s%s", ret->UUID, munchie);
 	free(munchie);
@@ -4354,8 +4359,10 @@ W("Validated session.");
 	  sesh *shs = &Rd->shs;
 
 	  qstrcpy(shs->leaf,		sizeof(shs->leaf),		leaf);
-	  shs->name =							tnm->getstr(tnm, "name",   true);	// LEAKY!
-	  shs->UUID =							tnm->getstr(tnm, "UUID",   true);	// LEAKY!
+	  if (NULL != shs->name)	free(shs->name);
+	  shs->name =							tnm->getstr(tnm, "name",   true);
+	  if (NULL != shs->UUID)	free(shs->UUID);
+	  shs->UUID =							tnm->getstr(tnm, "UUID",   true);
 	  if (linky)
 	  {
 W("Validated session linky.");
@@ -4562,7 +4569,8 @@ static int nameValidate(reqData *Rd, inputForm *iF, inputValue *iV)
 	Rd->stuff->putstrf(Rd->stuff, "name", "%s %s", name, s);
 // TODO - fix this, so we don't show "You are user" when we are not, but everything else still works.
 //	if ('\0' != getStrH(Rd->queries, "user")[0])
-	  Rd->shs.name = Rd->stuff->getstr(Rd->stuff, "name", true);	// LEAKY
+	  if (NULL != Rd->shs.name)	free(Rd->shs.name);
+	  Rd->shs.name = Rd->stuff->getstr(Rd->stuff, "name", true);
       }
     }
   }
@@ -4988,7 +4996,7 @@ static void accountLoginWeb(reqData *Rd, inputForm *oF, inputValue *oV)
 {
   if (NULL != Rd->shs.name)	free(Rd->shs.name);
   Rd->shs.name = NULL;
-//  if (NULL != Rd->shs.UUID)	free(Rd->shs.UUID);	// LEAKY!  And crashy!
+  if (NULL != Rd->shs.UUID)	free(Rd->shs.UUID);
   Rd->shs.UUID = NULL;
   accountWebHeaders(Rd, oF);
     accountWebFields(Rd, oF, oV);
@@ -5221,7 +5229,8 @@ d("accountRead() UUID %s, name %s %s", uuid, first, last);
     Rd->database->putstr(Rd->database, "Lua.vouched",			getStrH(tnm, "vouched"));
     Rd->database->putstr(Rd->database, "Lua.voucher",			getStrH(tnm, "voucher"));
   }
-  else if (rows)
+//  else if (rows)
+  if (rows)
   {
     ret += rows->rows->size(rows->rows);
     if (1 == ret)
@@ -5239,8 +5248,26 @@ d("accountRead() UUID %s, name %s %s", uuid, first, last);
       {
 	if (1 == rows->rows->size(rows->rows))
 	  dbPull(Rd, "auth", rows);
+	else
+        {
+	  free(rows->fieldNames);
+	  rows->rows->free(rows->rows);
+	  free(rows);
+	}
+      }
+      else
+      {
+	free(rows->fieldNames);
+	rows->rows->free(rows->rows);
+	free(rows);
       }
     }
+    else
+    {
+      free(rows->fieldNames);
+      rows->rows->free(rows->rows);
+      free(rows);
+    }
   }
   else
   {
@@ -5483,8 +5510,10 @@ d("Sub accountViewSub() %s  %s %s", uuid, first, last);
       else
       {
 	Rd->shs.level = atoi(getStrH(Rd->database, "UserAccounts.UserLevel"));
-	Rd->shs.name = Rd->database->getstr(Rd->database, "Lua.name", true);			// LEAKY
-	Rd->shs.UUID = Rd->database->getstr(Rd->database, "UserAccounts.PrincipalID", true);	// LEAKY
+	if (NULL != Rd->shs.name)	free(Rd->shs.name);
+	Rd->shs.name = Rd->database->getstr(Rd->database, "Lua.name", true);
+	if (NULL != Rd->shs.UUID)	free(Rd->shs.UUID);
+	Rd->shs.UUID = Rd->database->getstr(Rd->database, "UserAccounts.PrincipalID", true);
 	free(h);
 	I("Logged on %s  %s  Level %d %s", Rd->shs.UUID, Rd->shs.name, Rd->shs.level, getLevel(Rd->shs.level));
 	Rd->shs.status = SHS_LOGIN;
@@ -5677,7 +5706,7 @@ void inputFieldExtra(inputField *ret, signed char flags, short viewLength, short
 
 void addSession(inputForm *iF)
 {
-  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));		// LEAKY!
+  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));
 
 //d("addSession(%s)", iF->name);
   flds[0] = addInputField(iF, LUA_TSTRING,   "hashish",        "hashish",        "", sessionValidate, sessionWeb);
@@ -5693,7 +5722,7 @@ void addSession(inputForm *iF)
 
 void addEmailFields(inputForm *iF)
 {
-  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));		// LEAKY!
+  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));
 
   flds[0] = addInputField(iF, LUA_TEMAIL, "email", "email", NULL, emailValidate, emailWeb);
   inputFieldExtra(flds[0], FLD_EDITABLE, 42, 254);
@@ -5709,7 +5738,7 @@ void addEmailFields(inputForm *iF)
 
 void addDoBFields(inputForm *iF)
 {
-  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));		// LEAKY!
+  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));
 
   flds[0] = addInputField(iF, LUA_TSTRING, "DoByear", "year", NULL, DoBValidate, DoByWeb);
   flds[1] = addInputField(iF, LUA_TSTRING, "DoBmonth", "month", NULL, DoBValidate, DoBmWeb);
@@ -5722,7 +5751,7 @@ void addDoBFields(inputForm *iF)
 
 void addLegalFields(inputForm *iF)
 {
-  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));		// LEAKY!
+  inputField *fld, **flds = xzalloc(3 * sizeof(*flds));
 
   flds[0] = addInputField(iF, LUA_TBOOLEAN, "adult", "I'm allegedly an adult in my country.", NULL, legalValidate, adultWeb);
   flds[1] = addInputField(iF, LUA_TBOOLEAN, "agree", "I accept the Terms of Service.", NULL, legalValidate, agreeWeb);
@@ -6337,6 +6366,18 @@ static void cleanup(void)
 
 //d("%s = %s", obj.name, (char *) obj.data);
       f->subs->free(f->subs);
+      qlisttbl_obj_t fobj;
+
+      memset((void *) &fobj, 0, sizeof(fobj));
+      f->fields->lock(f->fields);
+      while(f->fields->getnext(f->fields, &fobj, NULL, false) == true)
+      {
+        inputField *fld = (inputField *) fobj.data;
+
+	if (LUA_TGROUP == fld->type)
+	  free(fld->group);
+      }
+      f->fields->unlock(f->fields);
       f->fields->free(f->fields);
     }
     accountPages->unlock(accountPages);
@@ -7081,7 +7122,7 @@ fcgiDone:
 	if (NULL != Rd->outQuery)	free(Rd->outQuery);
 	if (NULL != Rd->shs.name)	free(Rd->shs.name);
 	Rd->shs.name = NULL;
-//	if (NULL != Rd->shs.UUID)	free(Rd->shs.UUID);	// LEAKY!  But crashy!
+	if (NULL != Rd->shs.UUID)	free(Rd->shs.UUID);
 	Rd->shs.UUID = NULL;
 	qgrow_free(Rd->reply);
 	qlist_free(Rd->messages);
-- 
cgit v1.1