diff --git a/src/frontend/cpitf.c b/src/frontend/cpitf.c index 147bc73ed..4e869eabd 100644 --- a/src/frontend/cpitf.c +++ b/src/frontend/cpitf.c @@ -3,6 +3,11 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group **********/ +/* + * SJB 22 May 2001 + * Corrected freeing of memory in ft_cpinit() + */ + #include "ngspice.h" #include "cpdefs.h" #include "ftedefs.h" @@ -211,6 +216,7 @@ ft_cpinit(void) s++; for (r = buf; *s && !isspace(*s); r++, s++) *r = *s; + tfree(copys); /* sjb - it's safe to free this here */ (void) strcpy(r, DIR_PATHSEP); (void) strcat(r, "spinit"); if ((fp = fopen(buf, "r"))) { @@ -236,7 +242,8 @@ ft_cpinit(void) } tcap_init( ); - tfree(copys);/*DG Avoid memory leak*/ + /* tfree(copys);*/ /*DG Avoid memory leak*/ + /* SJB - must not free here as cp_tildexpande() can return NULL */ return; } diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 67d45cbaf..c73b98f92 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -3,6 +3,12 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher **********/ +/* + * SJB 22 May 2001 + * Fixed memory leaks accociated with freeing memory used by lines in the input deck + * in inp_spsource(). New line_free() routine added to help with this. + */ + /* * Stuff for dealing with spice input decks and command scripts, and * the listing routines. @@ -243,6 +249,25 @@ top2: return; } +/* + * Free memory used by a line. + * If recure is TRUE then recursivly free all lines linked via the li_next field. + * If recurse is FALSE free only this line. + * All lines linked via the li_actual field are always recursivly freed. + * SJB - 22nd May 2001 + */ +void +line_free(struct line * deck, bool recurse) { + if(!deck) + return; + tfree(deck->li_line); + tfree(deck->li_error); + if(recurse) + line_free(deck->li_next,TRUE); + line_free(deck->li_actual,TRUE); + tfree(deck); +} + /* The routine to source a spice input deck. We read the deck in, take * out the front-end commands, and create a CKT structure. Also we @@ -312,8 +337,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename) else cp_evloop(dd->li_line); } - tfree(dd->li_line); - tfree(dd); + line_free(dd,FALSE); /* SJB - free this line's memory */ + /* tfree(dd->li_line); + tfree(dd); */ } } else { for (dd = deck->li_next; dd; dd = ld->li_next) { @@ -332,8 +358,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename) if (ciprefix(".control", dd->li_line)) { ld->li_next = dd->li_next; - tfree(dd->li_line); - tfree(dd); + line_free(dd,FALSE); /* SJB - free this line's memory */ + /* tfree(dd->li_line); + tfree(dd); */ if (commands) fprintf(cp_err, "Warning: redundant .control card\n"); @@ -341,8 +368,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename) commands = TRUE; } else if (ciprefix(".endc", dd->li_line)) { ld->li_next = dd->li_next; - tfree(dd->li_line); - tfree(dd); + line_free(dd,FALSE); /* SJB - free this line's memory */ +/* tfree(dd->li_line); + tfree(dd); */ if (commands) commands = FALSE; else @@ -358,16 +386,20 @@ inp_spsource(FILE *fp, bool comfile, char *filename) controls = wl; if (prefix("*#", dd->li_line)) wl->wl_word = copy(dd->li_line + 2); - else + else { wl->wl_word = dd->li_line; + dd->li_line = 0; /* SJB - prevent line_free() freeing the string (now pointed at by wl->wl_word) */ + } ld->li_next = dd->li_next; - tfree(dd); + line_free(dd,FALSE); /* SJB - free this line's memory */ +/* tfree(dd); */ } else if (!*dd->li_line) { /* So blank lines in com files don't get considered as * circuits. */ ld->li_next = dd->li_next; - tfree(dd->li_line); - tfree(dd); + line_free(dd,FALSE); /* SJB - free this line's memory */ +/* tfree(dd->li_line); + tfree(dd); */ } else { inp_casefix(s); inp_casefix(dd->li_line); @@ -389,8 +421,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename) if (!eq(s, ".op") && !eq(s, ".tf")) { ld->li_next = dd->li_next; - tfree(dd->li_line); - tfree(dd); + line_free(dd,FALSE); /* SJB - free this line's memory */ +/* tfree(dd->li_line); + tfree(dd); */ } else ld = dd; } else @@ -406,6 +439,7 @@ inp_spsource(FILE *fp, bool comfile, char *filename) * commands. */ if (!cp_getvar("nosubckt", VT_BOOL, (char *) &nosubckts)) deck->li_next = inp_subcktexpand(deck->li_next); + line_free(deck->li_actual,FALSE); /* SJB - free memory used by old li_actual (if any) */ deck->li_actual = realdeck; inp_dodeck(deck, tt, wl_first, FALSE, options, filename); } diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index fe7ef42fd..9bb9f6375 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -6,6 +6,13 @@ Author: 1985 Wayne A. Christopher /* * For dealing with spice input decks and command scripts */ + +/* + * SJB 22 May 2001 + * Fixed memory leaks in inp_readall() when first(?) line of input begins with a '@'. + * Fixed memory leaks in inp_readall() when .include lines have errors + * Fixed crash where a NULL pointer gets freed in inp_readall() + */ #include #include "ngspice.h" @@ -117,8 +124,10 @@ inp_readall(FILE *fp, struct line **data) FILE *newfp; while ((buffer = readline(fp))) { - if (*buffer == '@') + if (*buffer == '@') { + tfree(buffer); /* was allocated by readline() */ break; + } for (s = buffer; *s && (*s != '\n'); s++) ; if (!*s) { @@ -132,24 +141,34 @@ inp_readall(FILE *fp, struct line **data) while (isspace(*s)) s++; if (!*s) { - fprintf(cp_err, - "Error: .include filename missing\n"); + fprintf(cp_err, "Error: .include filename missing\n"); + tfree(buffer); /* was allocated by readline() */ continue; } for (t = s; *t && !isspace(*t); t++) ; *t = '\0'; - if (*s == '~') - { - copys=cp_tildexpand(s); /*DG*/ - /*s = cp_tildexpand(s); very bad the last reference is los: memory leak*/ - strcpy(s,copys); - tfree(copys); - } + + if (*s == '~') { + copys = cp_tildexpand(s); /* allocates memory, but can also return NULL */ + if(copys != NULL) { + s = copys; /* reuse s, but remember, buffer still points to allocated memory */ + } + } + if (!(newfp = inp_pathopen(s, "r"))) { perror(s); + if(copys) { + tfree(copys); /* allocated by the cp_tildexpand() above */ + } + tfree(buffer); /* allocated by readline() above */ continue; } + + if(copys) { + tfree(copys); /* allocated by the cp_tildexpand() above */ + } + inp_readall(newfp, &newcard); (void) fclose(newfp);