From e6de94e677c203f8ea20949853fda5d879cd6f59 Mon Sep 17 00:00:00 2001 From: Stefan Farfeleder Date: Sun, 11 Mar 2007 18:30:22 +0000 Subject: [PATCH] Merge the following changes from NetBSD: chared.h 1.17, common.c 1.19, emacs.c 1.21, key.c 1.18, key.h 1.9, map.c 1.23, term.c 1.42, term.h 1.17, vi.c 1.25: # Print the actual eofc, instead of ^D\b\b. # Change internal character decoding to prevent buffer oveflows. key.c 1.19, key.h 1.10: # move declaration to header file. term.c 1.43: # Coverity CID 806: Prevent NULL deref term.c 1.44: # Coverity CID 1668: Plug memory leak. term.c 1.45: # Fix compilation. MFC after: 3 weeks --- lib/libedit/chared.h | 3 +- lib/libedit/common.c | 9 ++-- lib/libedit/emacs.c | 7 ++- lib/libedit/key.c | 125 ++++++++++++++++++++++++------------------- lib/libedit/key.h | 6 ++- lib/libedit/map.c | 35 +++++++----- lib/libedit/term.c | 44 ++++++++++++--- lib/libedit/term.h | 3 +- lib/libedit/vi.c | 7 ++- 9 files changed, 144 insertions(+), 95 deletions(-) diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h index 826c76786810..6636fc7b8610 100644 --- a/lib/libedit/chared.h +++ b/lib/libedit/chared.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)chared.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: chared.h,v 1.16 2005/08/08 14:05:37 christos Exp $ + * $NetBSD: chared.h,v 1.17 2006/03/06 21:11:56 christos Exp $ * $FreeBSD$ */ @@ -116,7 +116,6 @@ typedef struct el_chared_t { } el_chared_t; -#define STReof "^D\b\b" #define STRQQ "\"\"" #define isglob(a) (strchr("*[]?", (a)) != NULL) diff --git a/lib/libedit/common.c b/lib/libedit/common.c index 3259f0ab6972..d4a9fa302bbc 100644 --- a/lib/libedit/common.c +++ b/lib/libedit/common.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: common.c,v 1.18 2005/08/08 14:05:37 christos Exp $ + * $NetBSD: common.c,v 1.19 2006/03/06 21:11:56 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -135,7 +135,7 @@ ed_delete_prev_word(EditLine *el, int c __unused) */ protected el_action_t /*ARGSUSED*/ -ed_delete_next_char(EditLine *el, int c __unused) +ed_delete_next_char(EditLine *el, int c) { #ifdef notdef /* XXX */ #define EL el->el_line @@ -152,9 +152,8 @@ ed_delete_next_char(EditLine *el, int c __unused) #ifdef KSHVI return (CC_ERROR); #else - term_overwrite(el, STReof, 4); - /* then do an EOF */ - term__flush(); + /* then do an EOF */ + term_writechar(el, c); return (CC_EOF); #endif } else { diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c index c17788e1b84a..a285b1c305ee 100644 --- a/lib/libedit/emacs.c +++ b/lib/libedit/emacs.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: emacs.c,v 1.20 2005/08/08 14:05:37 christos Exp $ + * $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -50,15 +50,14 @@ __FBSDID("$FreeBSD$"); */ protected el_action_t /*ARGSUSED*/ -em_delete_or_list(EditLine *el, int c __unused) +em_delete_or_list(EditLine *el, int c) { if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */ if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */ - term_overwrite(el, STReof, 4); /* then do an EOF */ - term__flush(); + term_writec(el, c); /* then do an EOF */ return (CC_EOF); } else { /* diff --git a/lib/libedit/key.c b/lib/libedit/key.c index 16bfde699554..0b9d05d337b3 100644 --- a/lib/libedit/key.c +++ b/lib/libedit/key.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: key.c,v 1.17 2005/08/08 14:05:37 christos Exp $ + * $NetBSD: key.c,v 1.19 2006/03/23 20:22:51 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -88,7 +88,6 @@ private int node__delete(EditLine *, key_node_t **, const char *); private int node_lookup(EditLine *, const char *, key_node_t *, int); private int node_enum(EditLine *, key_node_t *, int); -private int key__decode_char(char *, int, int); #define KEY_BUFSIZ EL_BUFSIZ @@ -494,7 +493,7 @@ node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt) /* If match put this char into el->el_key.buf. Recurse */ if (ptr->ch == *str) { /* match found */ - ncnt = key__decode_char(el->el_key.buf, cnt, + ncnt = key__decode_char(el->el_key.buf, KEY_BUFSIZ, cnt, (unsigned char) ptr->ch); if (ptr->next != NULL) /* not yet at leaf */ @@ -548,7 +547,8 @@ node_enum(EditLine *el, key_node_t *ptr, int cnt) return (-1); } /* put this char at end of str */ - ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch); + ncnt = key__decode_char(el->el_key.buf, KEY_BUFSIZ, cnt, + (unsigned char)ptr->ch); if (ptr->next == NULL) { /* print this key and function */ el->el_key.buf[ncnt + 1] = '"'; @@ -579,9 +579,10 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) switch (ntype) { case XK_STR: case XK_EXE: - (void) fprintf(el->el_outfile, fmt, key, - key__decode_str(val->str, unparsbuf, - ntype == XK_STR ? "\"\"" : "[]")); + (void) key__decode_str(val->str, unparsbuf, + sizeof(unparsbuf), + ntype == XK_STR ? "\"\"" : "[]"); + (void) fprintf(el->el_outfile, fmt, key, unparsbuf); break; case XK_CMD: for (fp = el->el_map.help; fp->name; fp++) @@ -606,85 +607,99 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) } +#define ADDC(c) \ + if (b < eb) \ + *b++ = c; \ + else \ + b++ /* key__decode_char(): * Put a printable form of char in buf. */ -private int -key__decode_char(char *buf, int cnt, int ch) +protected int +key__decode_char(char *buf, int cnt, int off, int ch) { - ch = (unsigned char)ch; + char *sb = buf + off; + char *eb = buf + cnt; + char *b = sb; + ch = (unsigned char)ch; if (ch == 0) { - buf[cnt++] = '^'; - buf[cnt] = '@'; - return (cnt); + ADDC('^'); + ADDC('@'); + return b - sb; } if (iscntrl(ch)) { - buf[cnt++] = '^'; - if (ch == 0177) - buf[cnt] = '?'; + ADDC('^'); + if (ch == '\177') + ADDC('?'); else - buf[cnt] = toascii(ch) | 0100; + ADDC(toascii(ch) | 0100); } else if (ch == '^') { - buf[cnt++] = '\\'; - buf[cnt] = '^'; + ADDC('\\'); + ADDC('^'); } else if (ch == '\\') { - buf[cnt++] = '\\'; - buf[cnt] = '\\'; + ADDC('\\'); + ADDC('\\'); } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) { - buf[cnt] = ch; + ADDC(ch); } else { - buf[cnt++] = '\\'; - buf[cnt++] = (((unsigned int) ch >> 6) & 7) + '0'; - buf[cnt++] = (((unsigned int) ch >> 3) & 7) + '0'; - buf[cnt] = (ch & 7) + '0'; + ADDC('\\'); + ADDC((((unsigned int) ch >> 6) & 7) + '0'); + ADDC((((unsigned int) ch >> 3) & 7) + '0'); + ADDC((ch & 7) + '0'); } - return (cnt); + return b - sb; } /* key__decode_str(): * Make a printable version of the ey */ -protected char * -key__decode_str(const char *str, char *buf, const char *sep) +protected int +key__decode_str(const char *str, char *buf, int len, const char *sep) { - char *b; + char *b = buf, *eb = b + len; const char *p; b = buf; - if (sep[0] != '\0') - *b++ = sep[0]; - if (*str == 0) { - *b++ = '^'; - *b++ = '@'; - if (sep[0] != '\0' && sep[1] != '\0') - *b++ = sep[1]; - *b++ = 0; - return (buf); + if (sep[0] != '\0') { + ADDC(sep[0]); + } + if (*str == '\0') { + ADDC('^'); + ADDC('@'); + if (sep[0] != '\0' && sep[1] != '\0') { + ADDC(sep[1]); + } + goto done; } for (p = str; *p != 0; p++) { if (iscntrl((unsigned char) *p)) { - *b++ = '^'; - if (*p == '\177') - *b++ = '?'; - else - *b++ = toascii(*p) | 0100; + ADDC('^'); + if (*p == '\177') { + ADDC('?'); + } else { + ADDC(toascii(*p) | 0100); + } } else if (*p == '^' || *p == '\\') { - *b++ = '\\'; - *b++ = *p; + ADDC('\\'); + ADDC(*p); } else if (*p == ' ' || (isprint((unsigned char) *p) && !isspace((unsigned char) *p))) { - *b++ = *p; + ADDC(*p); } else { - *b++ = '\\'; - *b++ = (((unsigned int) *p >> 6) & 7) + '0'; - *b++ = (((unsigned int) *p >> 3) & 7) + '0'; - *b++ = (*p & 7) + '0'; + ADDC('\\'); + ADDC((((unsigned int) *p >> 6) & 7) + '0'); + ADDC((((unsigned int) *p >> 3) & 7) + '0'); + ADDC((*p & 7) + '0'); } } - if (sep[0] != '\0' && sep[1] != '\0') - *b++ = sep[1]; - *b++ = 0; - return (buf); /* should check for overflow */ + if (sep[0] != '\0' && sep[1] != '\0') { + ADDC(sep[1]); + } +done: + ADDC('\0'); + if (b - buf >= len) + buf[len - 1] = '\0'; + return b - buf; } diff --git a/lib/libedit/key.h b/lib/libedit/key.h index 0301f928cd30..3a212923b968 100644 --- a/lib/libedit/key.h +++ b/lib/libedit/key.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)key.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: key.h,v 1.8 2003/08/07 16:44:32 agc Exp $ + * $NetBSD: key.h,v 1.10 2006/03/23 20:22:51 christos Exp $ * $FreeBSD$ */ @@ -76,6 +76,8 @@ protected int key_delete(EditLine *, const char *); protected void key_print(EditLine *, const char *); protected void key_kprint(EditLine *, const char *, key_value_t *, int); -protected char *key__decode_str(const char *, char *, const char *); +protected int key__decode_str(const char *, char *, int, + const char *); +protected int key__decode_char(char *, int, int, int); #endif /* _h_el_key */ diff --git a/lib/libedit/map.c b/lib/libedit/map.c index 76c9e4d74f66..c4121a633801 100644 --- a/lib/libedit/map.c +++ b/lib/libedit/map.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: map.c,v 1.22 2005/08/09 13:58:44 christos Exp $ + * $NetBSD: map.c,v 1.23 2006/03/06 21:11:56 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -1126,7 +1126,7 @@ map_print_key(EditLine *el, el_action_t *map, const char *in) el_bindings_t *bp, *ep; if (in[0] == '\0' || in[1] == '\0') { - (void) key__decode_str(in, outbuf, ""); + (void) key__decode_str(in, outbuf, sizeof(outbuf), ""); ep = &el->el_map.help[el->el_map.nfunc]; for (bp = el->el_map.help; bp < ep; bp++) if (bp->func == map[(unsigned char) *in]) { @@ -1154,40 +1154,47 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) lastbuf[0] = last; lastbuf[1] = 0; if (map[first] == ED_UNASSIGNED) { - if (first == last) + if (first == last) { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, - "%-15s-> is undefined\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); + "%-15s-> is undefined\n", unparsbuf); + } return; } ep = &el->el_map.help[el->el_map.nfunc]; for (bp = el->el_map.help; bp < ep; bp++) { if (bp->func == map[first]) { if (first == last) { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "%-15s-> %s\n", - key__decode_str(firstbuf, unparsbuf, STRQQ), - bp->name); + unparsbuf, bp->name); } else { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); + (void) key__decode_str(lastbuf, extrabuf, + sizeof(extrabuf), STRQQ); (void) fprintf(el->el_outfile, "%-4s to %-7s-> %s\n", - key__decode_str(firstbuf, unparsbuf, STRQQ), - key__decode_str(lastbuf, extrabuf, STRQQ), - bp->name); + unparsbuf, extrabuf, bp->name); } return; } } #ifdef MAP_DEBUG if (map == el->el_map.key) { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, - "BUG!!! %s isn't bound to anything.\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); + "BUG!!! %s isn't bound to anything.\n", unparsbuf); (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n", first, el->el_map.key[first]); } else { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, - "BUG!!! %s isn't bound to anything.\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); + "BUG!!! %s isn't bound to anything.\n", unparsbuf); (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n", first, el->el_map.alt[first]); } diff --git a/lib/libedit/term.c b/lib/libedit/term.c index 6cd0e14e242c..eeadca07beb9 100644 --- a/lib/libedit/term.c +++ b/lib/libedit/term.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: term.c,v 1.41 2005/08/08 14:05:37 christos Exp $ + * $NetBSD: term.c,v 1.45 2006/03/18 19:23:14 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -386,7 +386,8 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) * New string is shorter; no need to allocate space */ if (clen <= tlen) { - (void) strcpy(*str, cap); /* XXX strcpy is safe */ + if (*str) + (void) strcpy(*str, cap); /* XXX strcpy is safe */ return; } /* @@ -460,8 +461,12 @@ term_alloc_display(EditLine *el) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - if (b[i] == NULL) + if (b[i] == NULL) { + while (--i >= 0) + el_free((ptr_t) b[i]); + el_free((ptr_t) b); return (-1); + } } b[c->v] = NULL; el->el_display = b; @@ -471,8 +476,12 @@ term_alloc_display(EditLine *el) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - if (b[i] == NULL) + if (b[i] == NULL) { + while (--i >= 0) + el_free((ptr_t) b[i]); + el_free((ptr_t) b); return (-1); + } } b[c->v] = NULL; el->el_vdisplay = b; @@ -1244,6 +1253,19 @@ term__flush(void) (void) fflush(term_outfile); } +/* term_writec(): + * Write the given character out, in a human readable form + */ +protected void +term_writec(EditLine *el, int c) +{ + char buf[8]; + int cnt = key__decode_char(buf, sizeof(buf), 0, c); + buf[cnt] = '\0'; + term_overwrite(el, buf, cnt); + term__flush(); +} + /* term_telltc(): * Print the current termcap characteristics @@ -1271,11 +1293,17 @@ term_telltc(EditLine *el, int argc __unused, (void) fprintf(el->el_outfile, "\tIt %s magic margins\n", EL_HAS_MAGIC_MARGINS ? "has" : "does not have"); - for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) + for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) { + const char *ub; + if (*ts && **ts) { + (void) key__decode_str(*ts, upbuf, sizeof(upbuf), ""); + ub = upbuf; + } else { + ub = "(empty)"; + } (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", - t->long_name, - t->name, *ts && **ts ? - key__decode_str(*ts, upbuf, "") : "(empty)"); + t->long_name, t->name, ub); + } (void) fputc('\n', el->el_outfile); return (0); } diff --git a/lib/libedit/term.h b/lib/libedit/term.h index d97b46d35789..95ad8f909487 100644 --- a/lib/libedit/term.h +++ b/lib/libedit/term.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)term.h 8.1 (Berkeley) 6/4/93 - * $NetBSD: term.h,v 1.16 2005/03/15 00:10:40 christos Exp $ + * $NetBSD: term.h,v 1.17 2006/03/06 21:11:56 christos Exp $ * $FreeBSD$ */ @@ -102,6 +102,7 @@ protected int term_set(EditLine *, const char *); protected int term_settc(EditLine *, int, const char **); protected int term_telltc(EditLine *, int, const char **); protected int term_echotc(EditLine *, int, const char **); +protected void term_writec(EditLine *, int); protected int term__putc(int); protected void term__flush(void); diff --git a/lib/libedit/vi.c b/lib/libedit/vi.c index 2d611fb307a3..ae57e07a01da 100644 --- a/lib/libedit/vi.c +++ b/lib/libedit/vi.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $NetBSD: vi.c,v 1.24 2005/08/10 12:46:24 christos Exp $ + * $NetBSD: vi.c,v 1.25 2006/03/06 21:11:56 christos Exp $ */ #if !defined(lint) && !defined(SCCSID) @@ -595,13 +595,12 @@ vi_delete_prev_char(EditLine *el, int c __unused) */ protected el_action_t /*ARGSUSED*/ -vi_list_or_eof(EditLine *el, int c __unused) +vi_list_or_eof(EditLine *el, int c) { if (el->el_line.cursor == el->el_line.lastchar) { if (el->el_line.cursor == el->el_line.buffer) { - term_overwrite(el, STReof, 4); /* then do a EOF */ - term__flush(); + term_writec(el, c); /* then do a EOF */ return (CC_EOF); } else { /*