From c1c939e34024d65087bce662dfed07a2f7639bfb Mon Sep 17 00:00:00 2001 From: tg Date: Sun, 9 Sep 2007 18:06:42 +0000 Subject: [PATCH] =?UTF-8?q?=E2=80=A2=20fix=20memory=20leaks=20found=20by?= =?UTF-8?q?=20coverity=20=20=20from=20netbsd=20via=20oksh=20=20=20we=20had?= =?UTF-8?q?=20the=20NULL=20pointer=20deref=20already=20fixed=20=E2=80=A2?= =?UTF-8?q?=20avoid=20a=20bogus=20not-setting=20the=20return=20value=20of?= =?UTF-8?q?=20edit.c:x=5Ffile=5Fglob()=20=20=20introduced=20by=20the=20abo?= =?UTF-8?q?ve=20change=20in=20oksh=20=E2=80=A2=20escape=20=3F=20as=20well?= =?UTF-8?q?=20(but=20not=20]=20because=20that=E2=80=99s=20wrong)=20=20=20r?= =?UTF-8?q?eminded=20by=20cbiere@netbsd=20via=20oksh=20=E2=80=A2=20Unsetti?= =?UTF-8?q?ng=20a=20non-existent=20variable=20is=20not=20an=20error.=20See?= =?UTF-8?q?=20=20=20http://www.opengroup.org/onlinepubs/009695399/utilitie?= =?UTF-8?q?s/unset.html=20=20=20report=20from=20Arkadiusz=20Miskiewicz;=20?= =?UTF-8?q?fixed=20based=20on=20=20=20http://cvs.pld-linux.org=20diff=20vi?= =?UTF-8?q?a=20oksh=20but=20modified=20slightly=20=E2=80=A2=20Be=20more=20?= =?UTF-8?q?smart=20waiting=20for=20input=20for=20non-interactive=20scripts?= =?UTF-8?q?.=20=20Fix=20=20=20based=20on=20a=20diff=20from=20debian:=20=20?= =?UTF-8?q?see=20their=20bug#296446=20(via=20oksh)=20=20=20modified=20slig?= =?UTF-8?q?htly=20=20=20this=20also=20fixes=20cnuke@=E2=80=99s=20=E2=80=9C?= =?UTF-8?q?mksh=20busy=20loop=E2=80=9D=20problem,=20for=20which=20I=20neve?= =?UTF-8?q?r=20=20=20received=20a=20bug=20report,=20but=20the=20Debian=20b?= =?UTF-8?q?ug=20page=20contains=20a=20set=20of=20two=20=20=20scripts=20to?= =?UTF-8?q?=20reproduce=20this=20before=20(and=20no=20longer=20after)=20th?= =?UTF-8?q?is=20commit=20=E2=80=A2=20some=20KNF=20=E2=80=A2=20bump=20versi?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check.t | 4 ++-- edit.c | 28 ++++++++++++++++------------ eval.c | 5 +++-- exec.c | 23 +++++++++++++++-------- funcs.c | 41 ++++++++++++++++++++++------------------- jobs.c | 13 ++++++++----- misc.c | 4 ++-- sh.h | 4 ++-- var.c | 13 ++++++++----- 9 files changed, 78 insertions(+), 57 deletions(-) diff --git a/check.t b/check.t index 7b19b73..114ac0c 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.137 2007/09/07 23:57:14 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.138 2007/09/09 18:06:38 tg Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ @@ -7,7 +7,7 @@ # http://www.research.att.com/~gsf/public/ifs.sh expected-stdout: - @(#)MIRBSD KSH R31 2007/08/19 + @(#)MIRBSD KSH R31 2007/09/09 description: Check version of shell. category: pdksh diff --git a/edit.c b/edit.c index 9955c80..2107bf1 100644 --- a/edit.c +++ b/edit.c @@ -1,11 +1,11 @@ -/* $OpenBSD: edit.c,v 1.31 2005/12/11 20:31:21 otto Exp $ */ +/* $OpenBSD: edit.c,v 1.33 2007/08/02 10:50:25 fgsch Exp $ */ /* $OpenBSD: edit.h,v 1.8 2005/03/28 21:28:22 deraadt Exp $ */ -/* $OpenBSD: emacs.c,v 1.40 2006/07/10 17:12:41 beck Exp $ */ +/* $OpenBSD: emacs.c,v 1.41 2007/08/02 10:50:25 fgsch Exp $ */ /* $OpenBSD: vi.c,v 1.23 2006/04/10 14:38:59 jaredy Exp $ */ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.111 2007/08/18 01:20:27 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.112 2007/09/09 18:06:39 tg Exp $"); /* tty driver characters we are interested in */ typedef struct { @@ -325,12 +325,14 @@ x_file_glob(int flags __unused, const char *str, int slen, char ***wordsp) stat(words[0], &statb) < 0) || words[0][0] == '\0') { x_free_words(nwords, words); + words = NULL; nwords = 0; } } afree(toglob, ATEMP); - *wordsp = nwords ? words : NULL; + if ((*wordsp = nwords ? words : NULL) == NULL && words != NULL) + x_free_words(nwords, words); return nwords; } @@ -729,7 +731,7 @@ x_escape(const char *s, size_t len, int (*putbuf_func)(const char *, size_t)) int rval = 0; while (wlen - add > 0) - if (vstrchr("\\$()[{}*&;#|<>\"'`", s[add]) || + if (vstrchr("\\$()[?{}*&;#|<>\"'`", s[add]) || vstrchr(ifs, s[add])) { if (putbuf_func(s, add) != 0) { rval = -1; @@ -1128,7 +1130,7 @@ static int x_search(char *, int, int); static int x_match(char *, char *); static void x_redraw(int); static void x_push(int); -static char * x_mapin(const char *); +static char * x_mapin(const char *, Area *); static char * x_mapout(int); static void x_mapout2(int, char **); static void x_print(int, int); @@ -2503,11 +2505,11 @@ x_error(int c __unused) } static char * -x_mapin(const char *cp) +x_mapin(const char *cp, Area *ap) { char *new, *op; - op = new = str_save(cp, ATEMP); + op = new = str_save(cp, ap); while (*cp) { /* XXX -- should handle \^ escape? */ if (*cp == '^') { @@ -2576,6 +2578,7 @@ x_bind(const char *a1, const char *a2, int prefix, key; char *sp = NULL; char *m1, *m2; + bool hastilde; if (x_tab == NULL) { bi_errorf("cannot bind, not a tty"); @@ -2600,7 +2603,7 @@ x_bind(const char *a1, const char *a2, } return (0); } - m1 = x_mapin(a1); + m2 = m1 = x_mapin(a1, ATEMP); prefix = key = 0; for (;; m1++) { key = *m1 & CHARMASK; @@ -2621,6 +2624,8 @@ x_bind(const char *a1, const char *a2, bi_errorf("%s' too long", msg); return (1); } + hastilde = *m1; + afree(m2, ATEMP); if (a2 == NULL) { x_print(prefix, key); @@ -2639,14 +2644,13 @@ x_bind(const char *a1, const char *a2, } } else { f = XFUNC_ins_string; - m2 = x_mapin(a2); - sp = str_save(m2, AEDIT); + sp = x_mapin(a2, AEDIT); } if ((x_tab[prefix][key] & 0x7F) == XFUNC_ins_string && x_atab[prefix][key]) afree((void *)x_atab[prefix][key], AEDIT); - x_tab[prefix][key] = f | ((*m1) ? 0x80 : 0); + x_tab[prefix][key] = f | (hastilde ? 0x80 : 0); x_atab[prefix][key] = sp; /* Track what the user has bound so x_mode(true) won't toast things */ diff --git a/eval.c b/eval.c index 366702e..dfbb764 100644 --- a/eval.c +++ b/eval.c @@ -1,8 +1,8 @@ -/* $OpenBSD: eval.c,v 1.30 2006/04/10 14:38:59 jaredy Exp $ */ +/* $OpenBSD: eval.c,v 1.33 2007/08/02 11:05:54 fgsch Exp $ */ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.34 2007/07/31 10:42:15 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.35 2007/09/09 18:06:39 tg Exp $"); #ifdef MKSH_SMALL #define MKSH_NOPWNAM @@ -903,6 +903,7 @@ comsub(Expand *xp, const char *cp) s->start = s->str = cp; sold = source; t = compile(s); + afree(s, ATEMP); source = sold; if (t == NULL) diff --git a/exec.c b/exec.c index 14a2d0a..7681bfa 100644 --- a/exec.c +++ b/exec.c @@ -1,8 +1,8 @@ -/* $OpenBSD: exec.c,v 1.46 2006/04/10 14:38:59 jaredy Exp $ */ +/* $OpenBSD: exec.c,v 1.48 2007/09/05 19:02:01 otto Exp $ */ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.37 2007/07/24 11:22:04 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.38 2007/09/09 18:06:40 tg Exp $"); static int comexec(struct op *, struct tbl *volatile, const char **, int volatile); @@ -881,7 +881,7 @@ findcom(const char *name, int flags) struct tbl *tp = NULL, *tbi; int insert = Flag(FTRACKALL); /* insert if not found */ char *fpath; /* for function autoloading */ - const char *npath; + union mksh_cchack npath; if (vstrchr(name, '/')) { insert = 0; @@ -934,14 +934,21 @@ findcom(const char *name, int flags) } tp->flag = DEFINED; /* make ~ISSET */ } - npath = search(name, flags & FC_DEFPATH ? def_path : path, + npath.ro = search(name, flags & FC_DEFPATH ? def_path : path, X_OK, &tp->u2.errno_); - if (npath) { - tp->val.s = str_save(npath, APERM); + if (npath.ro) { + /* XXX unsure about this, oksh does that + if (tp == &temp) + tp->val.s = npath.ro; + else */ { + tp->val.s = str_save(npath.ro, APERM); + if (npath.ro != name) + afree(npath.rw, ATEMP); + } tp->flag |= ISSET|ALLOC; } else if ((flags & FC_FUNC) && (fpath = str_val(global("FPATH"))) != null && - (npath = search(name, fpath, R_OK, + (npath.ro = search(name, fpath, R_OK, &tp->u2.errno_)) != NULL) { /* An undocumented feature of at&t ksh is that it * searches FPATH if a command is not found, even @@ -951,7 +958,7 @@ findcom(const char *name, int flags) tp = &temp; tp->type = CFUNC; tp->flag = DEFINED; /* make ~ISSET */ - tp->u.fpath = npath; + tp->u.fpath = npath.ro; } } return tp; diff --git a/funcs.c b/funcs.c index 4d1e965..f2f9828 100644 --- a/funcs.c +++ b/funcs.c @@ -1,11 +1,11 @@ -/* $OpenBSD: c_ksh.c,v 1.29 2006/03/12 00:26:58 deraadt Exp $ */ -/* $OpenBSD: c_sh.c,v 1.35 2006/04/10 14:38:59 jaredy Exp $ */ +/* $OpenBSD: c_ksh.c,v 1.30 2007/08/02 10:50:25 fgsch Exp $ */ +/* $OpenBSD: c_sh.c,v 1.37 2007/09/03 13:54:23 otto Exp $ */ /* $OpenBSD: c_test.c,v 1.17 2005/03/30 17:16:37 deraadt Exp $ */ /* $OpenBSD: c_ulimit.c,v 1.16 2006/11/20 21:53:39 miod Exp $ */ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.64 2007/08/19 23:12:21 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.65 2007/09/09 18:06:40 tg Exp $"); /* A leading = means assignments before command are kept; * a leading * means a POSIX special builtin; @@ -281,6 +281,7 @@ c_pwd(const char **wp) int optc; int physical = Flag(FPHYSICAL); char *p; + bool p_ = false; while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != -1) switch (optc) { @@ -303,11 +304,16 @@ c_pwd(const char **wp) NULL; if (p && access(p, R_OK) < 0) p = NULL; - if (!p && !(p = ksh_get_wd(NULL))) { - bi_errorf("can't get current directory - %s", strerror(errno)); - return 1; + if (!p) { + if (!(p = ksh_get_wd(NULL))) { + bi_errorf("can't get current directory - %s", + strerror(errno)); + return 1; + } + p_ = true; } shprintf("%s\n", p); + afreechv(p_, p); return 0; } @@ -1910,6 +1916,7 @@ c_eval(const char **wp) rv = shell(s, false); Flag(FERREXIT) = savef; source = saves; + afree(s, ATEMP); return (rv); } @@ -2090,37 +2097,33 @@ int c_unset(const char **wp) { const char *id; - int optc, unset_var = 1; - int ret = 0; + int optc; + bool unset_var = true; while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != -1) switch (optc) { case 'f': - unset_var = 0; + unset_var = false; break; case 'v': - unset_var = 1; + unset_var = true; break; case '?': - return 1; + return (1); } wp += builtin_opt.optind; for (; (id = *wp) != NULL; wp++) if (unset_var) { /* unset variable */ struct tbl *vp = global(id); - if (!(vp->flag & ISSET)) - ret = 1; if ((vp->flag&RDONLY)) { bi_errorf("%s is read only", vp->name); - return 1; + return (1); } unset(vp, vstrchr(id, '[') ? 1 : 0); - } else { /* unset function */ - if (define(id, (struct op *) NULL)) - ret = 1; - } - return ret; + } else /* unset function */ + define(id, NULL); + return (0); } static void diff --git a/jobs.c b/jobs.c index 1098d4e..2bd970e 100644 --- a/jobs.c +++ b/jobs.c @@ -1,8 +1,8 @@ -/* $OpenBSD: jobs.c,v 1.35 2006/02/06 16:47:07 jmc Exp $ */ +/* $OpenBSD: jobs.c,v 1.36 2007/09/06 19:57:47 otto Exp $ */ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.26 2007/08/12 13:42:21 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.27 2007/09/09 18:06:41 tg Exp $"); /* Order important! */ #define PRUNNING 0 @@ -214,11 +214,14 @@ j_change(void) int i; if (Flag(FMONITOR)) { + bool use_tty = Flag(FTALKING); + /* Don't call tcgetattr() 'til we own the tty process group */ - tty_init(false); + if (use_tty) + tty_init(false); /* no controlling tty, no SIGT* */ - ttypgrp_ok = tty_fd >= 0 && tty_devtty; + ttypgrp_ok = use_tty && tty_fd >= 0 && tty_devtty; if (ttypgrp_ok && (our_pgrp = getpgrp()) < 0) { warningf(false, "j_init: getpgrp() failed: %s", @@ -264,7 +267,7 @@ j_change(void) our_pgrp = kshpid; } } - if (!ttypgrp_ok) + if (use_tty && !ttypgrp_ok) warningf(false, "warning: won't have full job control"); if (tty_fd >= 0) tcgetattr(tty_fd, &tty_state); diff --git a/misc.c b/misc.c index f319d0e..997f400 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.30 2006/03/12 00:26:58 deraadt Exp $ */ +/* $OpenBSD: misc.c,v 1.32 2007/08/02 11:05:54 fgsch Exp $ */ /* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */ #include "sh.h" @@ -6,7 +6,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.65 2007/08/12 13:42:21 tg Exp $\t" +__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.66 2007/09/09 18:06:41 tg Exp $\t" MKSH_SH_H_ID); #undef USE_CHVT diff --git a/sh.h b/sh.h index 9c0dc3e..6d69867 100644 --- a/sh.h +++ b/sh.h @@ -8,8 +8,8 @@ /* $OpenBSD: c_test.h,v 1.4 2004/12/20 11:34:26 otto Exp $ */ /* $OpenBSD: tty.h,v 1.5 2004/12/20 11:34:26 otto Exp $ */ -#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.174 2007/08/20 14:06:10 tg Exp $" -#define MKSH_VERSION "R31 2007/08/19" +#define MKSH_SH_H_ID "$MirOS: src/bin/mksh/sh.h,v 1.175 2007/09/09 18:06:41 tg Exp $" +#define MKSH_VERSION "R31 2007/09/09" #if HAVE_SYS_PARAM_H #include diff --git a/var.c b/var.c index 6bc7c40..932e3ef 100644 --- a/var.c +++ b/var.c @@ -1,8 +1,8 @@ -/* $OpenBSD: var.c,v 1.30 2006/05/21 18:40:39 otto Exp $ */ +/* $OpenBSD: var.c,v 1.33 2007/08/02 11:05:54 fgsch Exp $ */ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/var.c,v 1.44 2007/08/20 13:57:47 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/var.c,v 1.45 2007/09/09 18:06:42 tg Exp $"); /* * Variables @@ -338,7 +338,9 @@ intval(struct tbl *vp) int setstr(struct tbl *vq, const char *s, int error_ok) { + char *salloc = NULL; int no_ro_check = error_ok & 0x4; + error_ok &= ~0x4; if ((vq->flag & RDONLY) && !no_ro_check) { warningf(true, "%s: is read only", vq->name); @@ -359,7 +361,7 @@ setstr(struct tbl *vq, const char *s, int error_ok) vq->flag &= ~(ISSET|ALLOC); vq->type = 0; if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST))) - s = formatstr(vq, s); + s = salloc = formatstr(vq, s); if ((vq->flag&EXPORT)) export(vq, s); else { @@ -368,12 +370,13 @@ setstr(struct tbl *vq, const char *s, int error_ok) } } else { /* integer dest */ if (!v_evaluate(vq, s, error_ok, true)) - return 0; + return (0); } vq->flag |= ISSET; if ((vq->flag&SPECIAL)) setspec(vq); - return 1; + afreechk(salloc); + return (1); } /* set variable to integer */