From 785b0cea557acd137776d890fceb4f03c82e4da3 Mon Sep 17 00:00:00 2001
From: Joerg Wunsch <j@uriah.heep.sax.de>
Date: Sat, 14 Mar 2020 22:34:45 +0000
Subject: [PATCH] patch #9819: Address several leaks in SVN rev 1429

Submitted by Adrian Klieber



git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@1435 81a1dc3b-b13d-400b-aceb-764788c761c2
---
 ChangeLog         | 10 ++++++++++
 NEWS              |  1 +
 config.c          |  2 ++
 jtagmkII.c        |  4 +++-
 stk500v2.c        |  4 ++++
 update.c          |  3 +++
 windows/loaddrv.c |  1 +
 7 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index ee0036b2..79d68be1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2020-03-14  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
+
+	Submitted by Adrian Klieber:
+	patch #9819: Address several leaks in SVN rev 1429
+	* config.c: Fix potential memory leak
+	* jtagmkII.c: (Dito.)
+	* stk500v2.c: (Dito.)
+	* update.c: (Dito.)
+	* windows/loaddrv.c: Fix file descriptor leak.
+
 2020-03-11  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
 
 	Submitted by: kautism
diff --git a/NEWS b/NEWS
index 2f495742..fca196d0 100644
--- a/NEWS
+++ b/NEWS
@@ -69,6 +69,7 @@ Current:
     patch #9735: spelling error fix: psuedo -> pseudo
     patch #9728: Fix UsbTiny programmer
     patch #9893: [PATCH] Reader reads ftdi handle after main thread close it
+    patch #9819: Address several leaks in SVN rev 1429
 
   * Internals:
     - New avrdude.conf keyword "family_id", used to verify SIB attributes
diff --git a/config.c b/config.c
index 08193cfc..9402e4bb 100644
--- a/config.c
+++ b/config.c
@@ -217,6 +217,7 @@ TOKEN * hexnumber(char * text)
   tkn->value.number = strtoul(text, &e, 16);
   if ((e == text) || (*e != 0)) {
     yyerror("can't scan hex number \"%s\"", text);
+    free_token(tkn);
     return NULL;
   }
   
@@ -244,6 +245,7 @@ TOKEN * string(char * text)
   tkn->value.string = (char *) malloc(len+1);
   if (tkn->value.string == NULL) {
     yyerror("string(): out of memory");
+    free_token(tkn);
     return NULL;
   }
   strcpy(tkn->value.string, text);
diff --git a/jtagmkII.c b/jtagmkII.c
index 2ccf87d9..2ccf9256 100644
--- a/jtagmkII.c
+++ b/jtagmkII.c
@@ -604,6 +604,7 @@ static int jtagmkII_recv_frame(PROGRAMMER * pgm, unsigned char **msg,
      if (tnow - tstart > timeoutval) {
        avrdude_message(MSG_INFO, "%s: jtagmkII_recv_frame(): timeout\n",
                progname);
+       free(buf);
        return -1;
      }
 
@@ -741,6 +742,7 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) {
 	  avrdude_message(MSG_NOTICE, "Device ID:                       %s\n",
 		  resp + 16);
 	}
+	free(resp);
 	break;
       }
       free(resp);
@@ -3634,12 +3636,12 @@ static int jtagmkII_paged_write32(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
     status = jtagmkII_flash_write_page32(pgm, pageNum);
     if(status < 0) {lineno = __LINE__; goto eRR;}
   }
-  free(cmd);
   serial_recv_timeout = otimeout;
 
   status = jtagmkII_reset32(pgm, AVR32_SET4RUNNING);  // AVR32_SET4RUNNING | AVR32_RELEASE_JTAG
   if(status < 0) {lineno = __LINE__; goto eRR;}
 
+  free(cmd);
   return addr;
 
   eRR:
diff --git a/stk500v2.c b/stk500v2.c
index 82050d36..9ee8588d 100644
--- a/stk500v2.c
+++ b/stk500v2.c
@@ -348,6 +348,9 @@ static void stk500v2_jtagmkII_teardown(PROGRAMMER * pgm)
 {
   void *mycookie;
 
+  free(PDATA(pgm)->flash_pagecache);
+  free(PDATA(pgm)->eeprom_pagecache);
+
   mycookie = pgm->cookie;
   pgm->cookie = PDATA(pgm)->chained_pdata;
   jtagmkII_teardown(pgm);
@@ -570,6 +573,7 @@ static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char *msg,
     return -1;
   }
   memcpy(msg, jtagmsg + 1, rv - 1);
+  free(jtagmsg);
   return rv;
 }
 
diff --git a/update.c b/update.c
index 1e35b571..bf6749d7 100644
--- a/update.c
+++ b/update.c
@@ -348,6 +348,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
       avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n",
               progname, mem->desc, rc);
       pgm->err_led(pgm, ON);
+      avr_free_part(v);
       return -1;
     }
     report_progress (1,1,NULL);
@@ -362,6 +363,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
       avrdude_message(MSG_INFO, "%s: verification error; content mismatch\n",
               progname);
       pgm->err_led(pgm, ON);
+      avr_free_part(v);
       return -1;
     }
 
@@ -371,6 +373,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
     }
 
     pgm->vfy_led(pgm, OFF);
+    avr_free_part(v);
   }
   else {
     avrdude_message(MSG_INFO, "%s: invalid update operation (%d) requested\n",
diff --git a/windows/loaddrv.c b/windows/loaddrv.c
index ca92a2a1..e6d55c66 100644
--- a/windows/loaddrv.c
+++ b/windows/loaddrv.c
@@ -45,6 +45,7 @@ void DisplayErrorText(DWORD dwLastError) {
 int exists(char *filename) {
     FILE * pFile;
     pFile = fopen(filename, "r");
+    if (pFile) fclose(pFile);
     return pFile != NULL;
 }