From eb79ead4f01c60456977a2d27909b4aca6c29336 Mon Sep 17 00:00:00 2001 From: Arun Kuruvila Date: Fri, 24 Apr 2015 11:30:13 +0530 Subject: [PATCH] Bug#20318154 : NEGATIVE ARRAY INDEX WRITE V2 Description:- There is a possibility of negative array index write associated with the function "terminal_writec()". This is due to the assumption that there is a possibility of getting -1 return value from the function call "ct_visual_char()". Analysis:- The function "terminal_writec()" is called only from "em_delete_or_list()" and "vi_list_or_eof()" and both these functions deal with the "^D" (ctrl+D) signal. So the "size_t len" and "Char c" passed to "ct_visual_char()" (when called from "terminal_writec()") is always 8 (macro VISUAL_WIDTH_MAX is passed whose value is 8) and 4 (ASCII value for "^D"/"ctrl+D") respectively. Since the value of "c" is 4, "ct_chr_class()" returns -1 (macro CHTYPE_ASCIICTL is associated with -1 value). And since value of "len" is 8, "ct_visual_char()" will always return 2 when it is called from "terminal_writec()". So there is no possible case so that we encounter a negative array index write in "terminal_writec()". But since there is a rare posibility of using "terminal_writec()" in future enhancements, it is good handle the error case as well. Fix:- A condition is added in "terminal_writec()" to check whether "ct_visual_char()" is returning -1 or not. If the return value is -1, then value 0 is returned to its calling function "em_delete_or_list()" or "vi_list_or_eof()", which in turn will return CC_ERROR. NOTE:- No testcase is added since currently there is no possible scenario to encounter this error case. --- cmd-line-utils/libedit/el_terminal.h | 4 ++-- cmd-line-utils/libedit/emacs.c | 8 +++++--- cmd-line-utils/libedit/terminal.c | 15 ++++++++++----- cmd-line-utils/libedit/vi.c | 8 +++++--- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/cmd-line-utils/libedit/el_terminal.h b/cmd-line-utils/libedit/el_terminal.h index 807c651783e..db0bb94fa93 100644 --- a/cmd-line-utils/libedit/el_terminal.h +++ b/cmd-line-utils/libedit/el_terminal.h @@ -1,7 +1,7 @@ /* $NetBSD: terminal.h,v 1.3 2011/07/29 23:44:45 christos Exp $ */ /*- - * Copyright (c) 1992, 1993 + * Copyright (c) 1992, 2015 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -103,7 +103,7 @@ protected int terminal_settc(EditLine *, int, const Char **); protected int terminal_gettc(EditLine *, int, char **); protected int terminal_telltc(EditLine *, int, const Char **); protected int terminal_echotc(EditLine *, int, const Char **); -protected void terminal_writec(EditLine *, Int); +protected int terminal_writec(EditLine *, Int); protected int terminal__putc(EditLine *, Int); protected void terminal__flush(EditLine *); diff --git a/cmd-line-utils/libedit/emacs.c b/cmd-line-utils/libedit/emacs.c index 554d3970485..1f1033a1cb7 100644 --- a/cmd-line-utils/libedit/emacs.c +++ b/cmd-line-utils/libedit/emacs.c @@ -1,7 +1,7 @@ /* $NetBSD: emacs.c,v 1.25 2011/07/29 15:16:33 christos Exp $ */ /*- - * Copyright (c) 1992, 1993 + * Copyright (c) 1992, 2015 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -58,8 +58,10 @@ em_delete_or_list(EditLine *el, Int c) /* if I'm at the end */ if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */ - terminal_writec(el, c); /* then do an EOF */ - return CC_EOF; + if(!(terminal_writec(el, c))) /* then do an EOF */ + return CC_EOF; + else + return CC_ERROR; } else { /* * Here we could list completions, but it is an diff --git a/cmd-line-utils/libedit/terminal.c b/cmd-line-utils/libedit/terminal.c index 8cfbeac7c52..e1f45ca1464 100644 --- a/cmd-line-utils/libedit/terminal.c +++ b/cmd-line-utils/libedit/terminal.c @@ -1,7 +1,7 @@ /* $NetBSD: terminal.c,v 1.10 2011/10/04 15:27:04 christos Exp $ */ /*- - * Copyright (c) 1992, 1993 + * Copyright (c) 1992, 2015 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -1271,14 +1271,19 @@ terminal__flush(EditLine *el) /* terminal_writec(): * Write the given character out, in a human readable form */ -protected void +protected int terminal_writec(EditLine *el, Int c) { Char visbuf[VISUAL_WIDTH_MAX +1]; ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); - visbuf[vcnt] = '\0'; - terminal_overwrite(el, visbuf, (size_t)vcnt); - terminal__flush(el); + if(vcnt == -1) + return 1; /* Error due to insufficient space */ + else { + visbuf[vcnt] = '\0'; + terminal_overwrite(el, visbuf, (size_t)vcnt); + terminal__flush(el); + return 0; + } } diff --git a/cmd-line-utils/libedit/vi.c b/cmd-line-utils/libedit/vi.c index 9a4b97a977e..41242030a98 100644 --- a/cmd-line-utils/libedit/vi.c +++ b/cmd-line-utils/libedit/vi.c @@ -1,7 +1,7 @@ /* $NetBSD: vi.c,v 1.41 2011/10/04 15:27:04 christos Exp $ */ /*- - * Copyright (c) 1992, 1993 + * Copyright (c) 1992, 2015 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -607,8 +607,10 @@ 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) { - terminal_writec(el, c); /* then do a EOF */ - return CC_EOF; + if(!(terminal_writec(el, c))) /* then do a EOF */ + return CC_EOF; + else + return CC_ERROR; } else { /* * Here we could list completions, but it is an