diff options
author | davidn <davidn@FreeBSD.org> | 1997-05-11 10:25:38 +0000 |
---|---|---|
committer | davidn <davidn@FreeBSD.org> | 1997-05-11 10:25:38 +0000 |
commit | d8d579b282a8c7b61c3c83ff57414748052f6b88 (patch) | |
tree | d1a6de04927c57ed8cad8a8716bafcf6555d5906 | |
parent | 665a2c9ba96ecde235da8598086244a85500020e (diff) | |
download | FreeBSD-src-d8d579b282a8c7b61c3c83ff57414748052f6b88.zip FreeBSD-src-d8d579b282a8c7b61c3c83ff57414748052f6b88.tar.gz |
Fix memory leak caused by not freeing memory returned by cgetstr()
calls. The cost is a little more up-front memory allocation, but the
effect seems minimal.
Problem noticed-by: bde
Added syslog at LOG_ERR when referencing an unknown gettytab entry
and for other cgetent() failues (circular reference et al).
To be merged into 2.2 after a few days testing.
-rw-r--r-- | libexec/getty/subr.c | 88 |
1 files changed, 80 insertions, 8 deletions
diff --git a/libexec/getty/subr.c b/libexec/getty/subr.c index 270db52..84cbefb 100644 --- a/libexec/getty/subr.c +++ b/libexec/getty/subr.c @@ -33,7 +33,7 @@ #ifndef lint /*static char sccsid[] = "from: @(#)subr.c 8.1 (Berkeley) 6/4/93";*/ -static char rcsid[] = "$Id$"; +static char rcsid[] = "$Id: subr.c,v 1.9 1997/02/22 14:21:40 peter Exp $"; #endif /* not lint */ /* @@ -46,6 +46,7 @@ static char rcsid[] = "$Id$"; #include <termios.h> #include <sys/ioctl.h> #include <sys/param.h> +#include <syslog.h> #ifdef DEBUG #include <stdio.h> #endif @@ -71,31 +72,101 @@ gettable(name, buf) register struct gettynums *np; register struct gettyflags *fp; long n; + int l; + char *p; + char *msg = NULL; const char *dba[2]; + + static int firsttime = 1; + dba[0] = _PATH_GETTYTAB; dba[1] = 0; - if (cgetent(&buf, dba, name) != 0) + if (firsttime) { + /* + * we need to strdup() anything in the strings array + * initially in order to simplify things later + */ + for (sp = gettystrs; sp->field; sp++) + if (sp->value != NULL) { + /* handle these ones more carefully */ + if (sp >= &gettystrs[4] && sp <= &gettystrs[6]) + l = 2; + else + l = strlen(sp->value) + 1; + if ((p = malloc(l)) != NULL) { + strncpy(p, sp->value, l); + p[l-1] = '\0'; + } + /* + * replace, even if NULL, else we'll + * have problems with free()ing static mem + */ + sp->value = p; + } + firsttime = 0; + } + + switch (cgetent(&buf, (char **)dba, (char *)name)) { + case 1: + msg = "%s: couldn't resolve 'tc=' in gettytab '%s'"; + case 0: + break; + case -1: + msg = "%s: unknown gettytab entry '%s'"; + break; + case -2: + msg = "%s: retrieving gettytab entry '%s': %m"; + break; + case -3: + msg = "%s: recursive 'tc=' reference gettytab entry '%s'"; + break; + default: + msg = "%s: unexpected cgetent() error for entry '%s'"; + break; + } + + if (msg != NULL) { + syslog(LOG_ERR, msg, "getty", name); return; + } + + for (sp = gettystrs; sp->field; sp++) { + if ((l = cgetstr(buf, (char*)sp->field, &p)) >= 0) { + if (sp->value) { + /* prefer existing value */ + if (strcmp(p, sp->value) != 0) + free(sp->value); + else { + free(p); + p = sp->value; + } + } + sp->value = p; + } else if (l == -1) { + free(sp->value); + sp->value = NULL; + } + } - for (sp = gettystrs; sp->field; sp++) - cgetstr(buf, sp->field, &sp->value); for (np = gettynums; np->field; np++) { - if (cgetnum(buf, np->field, &n) == -1) + if (cgetnum(buf, (char*)np->field, &n) == -1) np->set = 0; else { np->set = 1; np->value = n; } } + for (fp = gettyflags; fp->field; fp++) { - if (cgetcap(buf, fp->field, ':') == NULL) + if (cgetcap(buf, (char *)fp->field, ':') == NULL) fp->set = 0; else { fp->set = 1; fp->value = 1 ^ fp->invrt; } } + #ifdef DEBUG printf("name=\"%s\", buf=\"%s\"\r\n", name, buf); for (sp = gettystrs; sp->field; sp++) @@ -117,7 +188,7 @@ gendefaults() for (sp = gettystrs; sp->field; sp++) if (sp->value) - sp->defalt = sp->value; + sp->defalt = strdup(sp->value); for (np = gettynums; np->field; np++) if (np->set) np->defalt = np->value; @@ -137,7 +208,8 @@ setdefaults() for (sp = gettystrs; sp->field; sp++) if (!sp->value) - sp->value = sp->defalt; + sp->value = !sp->defalt ? sp->defalt + : strdup(sp->defalt); for (np = gettynums; np->field; np++) if (!np->set) np->value = np->defalt; |