Submitted By: Matt Burgess (matthew at linuxfromscratch dot org) Date: 2007-05-05 Initial Package Version: 5.6 Upstream Status: From Upstream Origin: ftp://invisible-island.net/ncurses/5.6/ncurses-5.6-coverity.patch.gz Description: Fixes a number of issues found by the Coverity static code analysis program. diff -Naur ncurses-5.6.orig/NEWS ncurses-5.6/NEWS --- ncurses-5.6.orig/NEWS 2006-12-17 20:36:26.000000000 +0000 +++ ncurses-5.6/NEWS 2007-05-05 08:11:08.000000000 +0000 @@ -45,6 +45,36 @@ Changes through 1.9.9e did not credit all contributions; it is not possible to add this information. +20060407 + > other fixes prompted by inspection for Coverity report: + + modify ifdef's for c++ binding to use try/catch/throw statements + + add a null-pointer check in tack/ansi.c request_cfss() + + fix a memory leak in ncurses/base/wresize.c + + corrected check for valid memu/meml capabilities in + progs/dump_entry.c when handling V_HPUX case. + > fixes based on Coverity report: + + remove dead code in test/bs.c + + remove dead code in test/demo_defkey.c + + remove an unused assignment in progs/infocmp.c + + fix a limit check in tack/ansi.c tools_charset() + + fix tack/ansi.c tools_status() to perform the VT320/VT420 + tests in request_cfss(). The function had exited too soon. + + fix a memory leak in tic.c's make_namelist() + + fix a couple of places in tack/output.c which did not check for EOF. + + fix a loop-condition in test/bs.c + + add index checks in lib_color.c for color palettes + + add index checks in progs/dump_entry.c for version_filter() handling + of V_BSD case. + + fix a possible null-pointer dereference in copywin() + + fix a possible null-pointer dereference in waddchnstr() + + add a null-pointer check in _nc_expand_try() + + add a null-pointer check in tic.c's make_namelist() + + add a null-pointer check in _nc_expand_try() + + add null-pointer checks in test/cardfile.c + + fix a double-free in ncurses/tinfo/trim_sgr0.c + + fix a double-free in ncurses/base/wresize.c + + add try/catch block to c++/cursesmain.cc + 20061217 5.6 release for upload to ftp.gnu.org 20061217 diff -Naur ncurses-5.6.orig/c++/cursesmain.cc ncurses-5.6/c++/cursesmain.cc --- ncurses-5.6.orig/c++/cursesmain.cc 2003-10-25 14:53:13.000000000 +0000 +++ ncurses-5.6/c++/cursesmain.cc 2007-05-05 08:11:08.000000000 +0000 @@ -34,6 +34,13 @@ #include "internal.h" #include "cursesapp.h" +#if CPP_HAS_TRY_CATCH && HAVE_IOSTREAM +#include +#else +#undef CPP_HAS_TRY_CATCH +#define CPP_HAS_TRY_CATCH 0 +#endif + MODULE_ID("$Id: cursesmain.cc,v 1.11 2003/10/25 14:53:13 tom Exp $") #if HAVE_LOCALE_H @@ -58,8 +65,20 @@ A->handleArgs(argc,argv); ::endwin(); +#if CPP_HAS_TRY_CATCH + try { + res = (*A)(); + ::endwin(); + } + catch(const NCursesException &e) { + ::endwin(); + std::cerr << e.message << std::endl; + res = e.errorno; + } +#else res = (*A)(); ::endwin(); +#endif return(res); } } diff -Naur ncurses-5.6.orig/c++/cursesp.h ncurses-5.6/c++/cursesp.h --- ncurses-5.6.orig/c++/cursesp.h 2005-08-13 18:09:21.000000000 +0000 +++ ncurses-5.6/c++/cursesp.h 2007-05-05 08:11:08.000000000 +0000 @@ -83,7 +83,7 @@ return uptr->m_user; } - void OnError (int err) const THROWS((NCursesPanelException)) + void OnError (int err) const THROWS(NCursesPanelException) { if (err==ERR) THROW(new NCursesPanelException (this, err)); diff -Naur ncurses-5.6.orig/c++/etip.h.in ncurses-5.6/c++/etip.h.in --- ncurses-5.6.orig/c++/etip.h.in 2005-08-06 19:55:57.000000000 +0000 +++ ncurses-5.6/c++/etip.h.in 2007-05-05 08:11:08.000000000 +0000 @@ -342,23 +342,33 @@ inline void THROW(const NCursesException *e) { #if defined(__GNUG__) && defined(__EXCEPTIONS) # if ((__GNUG__ <= 2) && (__GNUC_MINOR__ < 8)) - (*lib_error_handler)(e?e->classname():"",e?e->message:""); + (*lib_error_handler)(e ? e->classname() : "", e ? e->message : ""); #else - throw *e; +#define CPP_HAS_TRY_CATCH 1 #endif #elif defined(__SUNPRO_CC) # if !defined(__SUNPRO_CC_COMPAT) || (__SUNPRO_CC_COMPAT < 5) genericerror(1, ((e != 0) ? (char *)(e->message) : "")); #else - throw *e; +#define CPP_HAS_TRY_CATCH 1 #endif #else if (e) cerr << e->message << endl; exit(0); #endif -} -#define THROWS(s) +#ifndef CPP_HAS_TRY_CATCH +#define CPP_HAS_TRY_CATCH 0 +#define NCURSES_CPP_TRY /* nothing */ +#define NCURSES_CPP_CATCH(e) if (false) +#define THROWS(s) /* nothing */ +#elif CPP_HAS_TRY_CATCH + throw *e; +#define NCURSES_CPP_TRY try +#define NCURSES_CPP_CATCH(e) catch(e) +#define THROWS(s) throw(s) +#endif +} #endif /* NCURSES_ETIP_H_incl */ diff -Naur ncurses-5.6.orig/configure ncurses-5.6/configure --- ncurses-5.6.orig/configure 2006-12-17 16:33:38.000000000 +0000 +++ ncurses-5.6/configure 2007-05-05 08:11:08.000000000 +0000 @@ -13865,7 +13865,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_main_return=return -for ac_header in typeinfo +for ac_header in iostream typeinfo do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:13871: checking for $ac_header" >&5 diff -Naur ncurses-5.6.orig/configure.in ncurses-5.6/configure.in --- ncurses-5.6.orig/configure.in 2006-12-17 01:26:06.000000000 +0000 +++ ncurses-5.6/configure.in 2007-05-05 08:11:08.000000000 +0000 @@ -1200,7 +1200,7 @@ ;; esac - AC_CHECK_HEADERS(typeinfo) + AC_CHECK_HEADERS(iostream typeinfo) CF_BOOL_DECL CF_BOOL_SIZE diff -Naur ncurses-5.6.orig/include/ncurses_defs ncurses-5.6/include/ncurses_defs --- ncurses-5.6.orig/include/ncurses_defs 2006-08-05 19:27:02.000000000 +0000 +++ ncurses-5.6/include/ncurses_defs 2007-05-05 08:11:08.000000000 +0000 @@ -68,6 +68,7 @@ HAVE_GPP_BUILTIN_H HAVE_GXX_BUILTIN_H HAVE_HAS_KEY +HAVE_IOSTREAM HAVE_ISASCII HAVE_ISSETUGID HAVE_LANGINFO_CODESET diff -Naur ncurses-5.6.orig/ncurses/base/lib_addstr.c ncurses-5.6/ncurses/base/lib_addstr.c --- ncurses-5.6.orig/ncurses/base/lib_addstr.c 2006-05-27 19:22:19.000000000 +0000 +++ ncurses-5.6/ncurses/base/lib_addstr.c 2007-05-05 08:11:08.000000000 +0000 @@ -80,8 +80,7 @@ NCURSES_EXPORT(int) waddchnstr(WINDOW *win, const chtype *astr, int n) { - NCURSES_SIZE_T y = win->_cury; - NCURSES_SIZE_T x = win->_curx; + NCURSES_SIZE_T y, x; int code = OK; int i; struct ldat *line; @@ -91,6 +90,8 @@ if (!win) returnCode(ERR); + y = win->_cury; + x = win->_curx; if (n < 0) { const chtype *str; n = 0; diff -Naur ncurses-5.6.orig/ncurses/base/lib_color.c ncurses-5.6/ncurses/base/lib_color.c --- ncurses-5.6.orig/ncurses/base/lib_color.c 2006-11-26 01:33:16.000000000 +0000 +++ ncurses-5.6/ncurses/base/lib_color.c 2007-05-05 08:11:08.000000000 +0000 @@ -56,7 +56,10 @@ #define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts)) +#define MAX_PALETTE 8 + #define OkColorHi(n) (((n) < COLORS) && ((n) < max_colors)) +#define InPalette(n) ((n) >= 0 && (n) < MAX_PALETTE) /* * Given a RGB range of 0..1000, we'll normally set the individual values @@ -162,10 +165,10 @@ tp = (hue_lightness_saturation) ? hls_palette : cga_palette; for (n = 0; n < COLORS; n++) { - if (n < 8) { + if (InPalette(n)) { SP->_color_table[n] = tp[n]; } else { - SP->_color_table[n] = tp[n % 8]; + SP->_color_table[n] = tp[n % MAX_PALETTE]; if (hue_lightness_saturation) { SP->_color_table[n].green = 100; } else { @@ -365,7 +368,7 @@ if (GET_SCREEN_PAIR(SP) == pair) SET_SCREEN_PAIR(SP, (chtype) (~0)); /* force attribute update */ - if (initialize_pair) { + if (initialize_pair && InPalette(f) && InPalette(b)) { const color_t *tp = hue_lightness_saturation ? hls_palette : cga_palette; T(("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)", diff -Naur ncurses-5.6.orig/ncurses/base/lib_overlay.c ncurses-5.6/ncurses/base/lib_overlay.c --- ncurses-5.6.orig/ncurses/base/lib_overlay.c 2006-10-14 20:43:31.000000000 +0000 +++ ncurses-5.6/ncurses/base/lib_overlay.c 2007-05-05 08:11:08.000000000 +0000 @@ -139,8 +139,8 @@ { int sx, sy, dx, dy; bool touched; - attr_t bk = AttrOf(dst->_nc_bkgd); - attr_t mask = ~(attr_t) ((bk & A_COLOR) ? A_COLOR : 0); + attr_t bk; + attr_t mask; T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"), src, dst, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, over)); @@ -148,6 +148,9 @@ if (!src || !dst) returnCode(ERR); + bk = AttrOf(dst->_nc_bkgd); + mask = ~(attr_t) ((bk & A_COLOR) ? A_COLOR : 0); + /* make sure rectangle exists in source */ if ((sminrow + dmaxrow - dminrow) > (src->_maxy + 1) || (smincol + dmaxcol - dmincol) > (src->_maxx + 1)) { diff -Naur ncurses-5.6.orig/ncurses/base/tries.c ncurses-5.6/ncurses/base/tries.c --- ncurses-5.6.orig/ncurses/base/tries.c 2005-11-26 20:09:18.000000000 +0000 +++ ncurses-5.6/ncurses/base/tries.c 2007-05-05 08:11:08.000000000 +0000 @@ -68,7 +68,7 @@ } } if (result != 0) { - if ((result[len] = ptr->ch) == 0) + if (ptr != 0 && (result[len] = ptr->ch) == 0) *((unsigned char *) (result + len)) = 128; #ifdef TRACE if (len == 0 && _nc_tracing != 0) diff -Naur ncurses-5.6.orig/ncurses/base/wresize.c ncurses-5.6/ncurses/base/wresize.c --- ncurses-5.6.orig/ncurses/base/wresize.c 2006-10-14 20:43:31.000000000 +0000 +++ ncurses-5.6/ncurses/base/wresize.c 2007-05-05 08:11:08.000000000 +0000 @@ -38,7 +38,7 @@ cleanup_lines(struct ldat *data, int length) { while (--length >= 0) - free(data->text); + free(data[length].text); free(data); return ERR; } diff -Naur ncurses-5.6.orig/ncurses/tinfo/trim_sgr0.c ncurses-5.6/ncurses/tinfo/trim_sgr0.c --- ncurses-5.6.orig/ncurses/tinfo/trim_sgr0.c 2006-12-02 19:37:57.000000000 +0000 +++ ncurses-5.6/ncurses/tinfo/trim_sgr0.c 2007-05-05 08:11:08.000000000 +0000 @@ -247,9 +247,7 @@ if (!rewrite_sgr(on, enter_alt_charset_mode) || !rewrite_sgr(off, exit_alt_charset_mode) || !rewrite_sgr(end, exit_alt_charset_mode)) { - FreeIfNeeded(on); FreeIfNeeded(off); - FreeIfNeeded(end); } else if (similar_sgr(off, end) && !similar_sgr(off, on)) { TR(TRACE_DATABASE, ("adjusting sgr(9:off) : %s", _nc_visbuf(off))); @@ -315,8 +313,8 @@ */ free(off); } - free(end); - free(on); + FreeIfNeeded(end); + FreeIfNeeded(on); } else { /* * Possibly some applications are confused if sgr0 contains rmacs, diff -Naur ncurses-5.6.orig/progs/dump_entry.c ncurses-5.6/progs/dump_entry.c --- ncurses-5.6.orig/progs/dump_entry.c 2006-09-30 20:18:15.000000000 +0000 +++ ncurses-5.6/progs/dump_entry.c 2007-05-05 08:11:08.000000000 +0000 @@ -352,14 +352,17 @@ } break; +#define is_termcap(type) (idx < (int) sizeof(type##_from_termcap) && \ + type##_from_termcap[idx]) + case V_BSD: /* BSD */ switch (type) { case BOOLEAN: - return bool_from_termcap[idx]; + return is_termcap(bool); case NUMBER: - return num_from_termcap[idx]; + return is_termcap(num); case STRING: - return str_from_termcap[idx]; + return is_termcap(str); } break; } @@ -788,11 +791,11 @@ * Much more work should be done on this to support dumping termcaps. */ if (tversion == V_HPUX) { - if (memory_lock) { + if (VALID_STRING(memory_lock)) { (void) sprintf(buffer, "meml=%s", memory_lock); WRAP_CONCAT; } - if (memory_unlock) { + if (VALID_STRING(memory_unlock)) { (void) sprintf(buffer, "memu=%s", memory_unlock); WRAP_CONCAT; } diff -Naur ncurses-5.6.orig/progs/infocmp.c ncurses-5.6/progs/infocmp.c --- ncurses-5.6.orig/progs/infocmp.c 2006-08-19 21:20:37.000000000 +0000 +++ ncurses-5.6/progs/infocmp.c 2007-05-05 08:11:08.000000000 +0000 @@ -1083,7 +1083,6 @@ } *tp++ = '"'; *tp = '\0'; - size += (strlen(term->Strings[n]) + 1); (void) printf("static char %-20s[] = %s;\n", string_variable(ExtStrname(term, n, strnames)), buf); } diff -Naur ncurses-5.6.orig/progs/tic.c ncurses-5.6/progs/tic.c --- ncurses-5.6.orig/progs/tic.c 2006-12-02 22:13:17.000000000 +0000 +++ ncurses-5.6/progs/tic.c 2007-05-05 08:11:08.000000000 +0000 @@ -353,11 +353,24 @@ return fp; } +#if NO_LEAKS +static void +free_namelist(char **src) +{ + if (src != 0) { + int n; + for (n = 0; src[n] != 0; ++n) + free (src[n]); + free (src); + } +} +#endif + /* Parse the "-e" option-value into a list of names */ -static const char ** +static char ** make_namelist(char *src) { - const char **dst = 0; + char **dst = 0; char *s, *base; unsigned pass, n, nn; @@ -374,11 +387,13 @@ if ((s = stripped(buffer)) != 0) { if (dst != 0) dst[nn] = s; + else + free(s); nn++; } } if (pass == 1) { - dst = typeCalloc(const char *, nn + 1); + dst = typeCalloc(char *, nn + 1); rewind(fp); } } @@ -401,10 +416,10 @@ break; } if (pass == 1) - dst = typeCalloc(const char *, nn + 1); + dst = typeCalloc(char *, nn + 1); } } - if (showsummary) { + if (showsummary && (dst != 0)) { fprintf(log_fp, "Entries that will be compiled:\n"); for (n = 0; dst[n] != 0; n++) fprintf(log_fp, "%u:%s\n", n + 1, dst[n]); @@ -413,7 +428,7 @@ } static bool -matches(const char **needle, const char *haystack) +matches(char **needle, const char *haystack) /* does entry in needle list match |-separated field in haystack? */ { bool code = FALSE; @@ -468,7 +483,7 @@ bool limited = TRUE; char *tversion = (char *) NULL; const char *source_file = "terminfo"; - const char **namelst = 0; + char **namelst = 0; char *outdir = (char *) NULL; bool check_only = FALSE; bool suppress_untranslatable = FALSE; @@ -784,6 +799,9 @@ else fprintf(log_fp, "No entries written\n"); } +#if NO_LEAKS + free_namelist(namelst); +#endif cleanup(); ExitProgram(EXIT_SUCCESS); } diff -Naur ncurses-5.6.orig/tack/ansi.c ncurses-5.6/tack/ansi.c --- ncurses-5.6.orig/tack/ansi.c 2005-09-17 19:49:16.000000000 +0000 +++ ncurses-5.6/tack/ansi.c 2007-05-05 08:11:08.000000000 +0000 @@ -309,6 +309,8 @@ put_crlf(); for (i = 0; rqss[i].text; i++) { ptext(rqss[i].text); + if (rqss[i].expect == 0) + continue; j = strlen(rqss[i].text) + strlen(rqss[i].expect); putchp(' '); for (j++; j < 40; j++) @@ -600,10 +602,11 @@ i = read_reports(); if (i != 'r' && i != 'R') { *ch = i; - return; + break; } } while (i); + /* VT320, VT420, etc. */ if (terminal_class >= 63) { do { i = request_cfss(); @@ -841,7 +844,7 @@ bank[j] = ch; if (ch < ' ' || ch > '/') break; - if (j + 1 >= (int) sizeof(bank)) + if (j + 2 >= (int) sizeof(bank)) break; } if (j == 1) diff -Naur ncurses-5.6.orig/tack/output.c ncurses-5.6/tack/output.c --- ncurses-5.6.orig/tack/output.c 2006-11-26 00:16:49.000000000 +0000 +++ ncurses-5.6/tack/output.c 2007-05-05 08:11:08.000000000 +0000 @@ -740,7 +740,9 @@ /* ignore control S, but tell me about it */ while (ch == 023 || ch == 021) { ch = getchp(STRIP_PARITY); - if (i < (int) sizeof(cc)) + if (ch == EOF) + break; + if (i + 1 < (int) sizeof(cc)) cc[++i] = ch; } put_str("\nThe terminal sent a ^S -"); @@ -778,7 +780,7 @@ for (i = 0; i < length - 1; ) { ch = getchp(STRIP_PARITY); - if (ch == '\r' || ch == '\n') { + if (ch == '\r' || ch == '\n' || ch == EOF) { break; } if (ch == '\b' || ch == 127) { diff -Naur ncurses-5.6.orig/test/bs.c ncurses-5.6/test/bs.c --- ncurses-5.6.orig/test/bs.c 2006-05-20 15:38:52.000000000 +0000 +++ ncurses-5.6/test/bs.c 2007-05-05 08:11:08.000000000 +0000 @@ -459,7 +459,7 @@ do { c = getch(); } while - (!strchr("hjklrR", c) || c == FF); + (!(strchr("hjklrR", c) || c == FF)); if (c == FF) { (void) clearok(stdscr, TRUE); diff -Naur ncurses-5.6.orig/test/cardfile.c ncurses-5.6/test/cardfile.c --- ncurses-5.6.orig/test/cardfile.c 2006-12-10 00:30:09.000000000 +0000 +++ ncurses-5.6/test/cardfile.c 2007-05-05 08:11:08.000000000 +0000 @@ -136,13 +136,15 @@ if ((offset = strlen(card->content)) != 0) { total += 1 + offset; card->content = (char *) realloc(card->content, total + 1); - strcpy(card->content + offset++, " "); + if (card->content) + strcpy(card->content + offset++, " "); } else { if (card->content != 0) free(card->content); card->content = (char *) malloc(total + 1); } - strcpy(card->content + offset, content); + if (card->content) + strcpy(card->content + offset, content); } } diff -Naur ncurses-5.6.orig/test/demo_defkey.c ncurses-5.6/test/demo_defkey.c --- ncurses-5.6.orig/test/demo_defkey.c 2006-04-01 19:08:03.000000000 +0000 +++ ncurses-5.6/test/demo_defkey.c 2007-05-05 08:11:08.000000000 +0000 @@ -143,13 +143,12 @@ code_name); } log_last_line(win); + if (vis_string != 0) { free(vis_string); vis_string = 0; } - if (vis_string != 0) - free(vis_string); vis_string = visible(new_string); if ((rc = key_defined(new_string)) > 0) { wprintw(win, "%s was bound to %s\n", vis_string, keyname(rc));