| From 4bf72cb8f1d3aa5f33c31eb817a5f0338f4aaf6f Mon Sep 17 00:00:00 2001 |
| From: Ovidiu Panait <ovidiu.panait@windriver.com> |
| Date: Wed, 20 Sep 2017 05:02:00 +0000 |
| Subject: [PATCH] Import upstream patch 20170826 |
| |
| 20170826 |
| + fixes for "iterm2" (report by Leonardo Brondani Schenkel) -TD |
| + corrected a warning from tic about keys which are the same, to skip |
| over missing/cancelled values. |
| + add check in tic for unnecessary use of "2" to denote a shifted |
| special key. |
| + improve checks in trim_sgr0, comp_parse.c and parse_entry.c, for |
| cancelled string capabilities. |
| + add check in _nc_parse_entry() for invalid entry name, setting the |
| name to "invalid" to avoid problems storing entries. |
| + add/improve checks in tic's parser to address invalid input |
| + add a check in comp_scan.c to handle the special case where a |
| nontext file ending with a NUL rather than newline is given to tic |
| as input (Redhat #1484274). |
| + allow for cancelled capabilities in _nc_save_str (Redhat #1484276). |
| + add validity checks for "use=" target in _nc_parse_entry (Redhat |
| #1484284). |
| + check for invalid strings in postprocess_termcap (Redhat #1484285) |
| + reset secondary pointers on EOF in next_char() (Redhat #1484287). |
| + guard _nc_safe_strcpy() and _nc_safe_strcat() against calls using |
| cancelled strings (Redhat #1484291). |
| + correct typo in curs_memleaks.3x (Sven Joachim). |
| + improve test/configure checks for some curses variants not based on |
| X/Open Curses. |
| + add options for test/configure to disable checks for form, menu and |
| panel libraries. |
| |
| Upstream-Status: Backport |
| CVE: CVE-2017-13732, CVE-2017-13734, CVE-2017-13730, CVE-2017-13729, CVE-2017-13728, CVE-2017-13731 |
| |
| |
| Author: Sven Joachim <svenjoac@gmx.de> |
| Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com> |
| --- |
| dist.mk | 4 +- |
| include/ncurses_defs | 4 +- |
| ncurses/tinfo/alloc_entry.c | 4 +- |
| ncurses/tinfo/comp_parse.c | 10 ++--- |
| ncurses/tinfo/comp_scan.c | 6 ++- |
| ncurses/tinfo/parse_entry.c | 91 ++++++++++++++++++++++++++++++--------------- |
| ncurses/tinfo/strings.c | 9 +++-- |
| ncurses/tinfo/trim_sgr0.c | 4 +- |
| progs/tic.c | 75 ++++++++++++++++++++++++++++++++++++- |
| 9 files changed, 157 insertions(+), 50 deletions(-) |
| |
| diff --git a/dist.mk b/dist.mk |
| index 9af2699..2c70472 100644 |
| --- a/dist.mk |
| +++ b/dist.mk |
| @@ -25,7 +25,7 @@ |
| # use or other dealings in this Software without prior written # |
| # authorization. # |
| ############################################################################## |
| -# $Id: dist.mk,v 1.1172 2017/07/13 00:15:27 tom Exp $ |
| +# $Id: dist.mk,v 1.1179 2017/08/20 15:33:41 tom Exp $ |
| # Makefile for creating ncurses distributions. |
| # |
| # This only needs to be used directly as a makefile by developers, but |
| @@ -37,7 +37,7 @@ SHELL = /bin/sh |
| # These define the major/minor/patch versions of ncurses. |
| NCURSES_MAJOR = 6 |
| NCURSES_MINOR = 0 |
| -NCURSES_PATCH = 20170715 |
| +NCURSES_PATCH = 20170826 |
| |
| # We don't append the patch to the version, since this only applies to releases |
| VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR) |
| diff --git a/include/ncurses_defs b/include/ncurses_defs |
| index e6611b7..d237db1 100644 |
| --- a/include/ncurses_defs |
| +++ b/include/ncurses_defs |
| @@ -1,4 +1,4 @@ |
| -# $Id: ncurses_defs,v 1.73 2017/06/24 14:20:57 tom Exp $ |
| +# $Id: ncurses_defs,v 1.75 2017/08/20 16:50:04 tom Exp $ |
| ############################################################################## |
| # Copyright (c) 2000-2016,2017 Free Software Foundation, Inc. # |
| # # |
| @@ -50,7 +50,9 @@ HAVE_BSD_STRING_H |
| HAVE_BTOWC |
| HAVE_BUILTIN_H |
| HAVE_CHGAT 1 |
| +HAVE_COLOR_CONTENT 1 |
| HAVE_COLOR_SET 1 |
| +HAVE_CURSCR 1 |
| HAVE_DIRENT_H |
| HAVE_ERRNO |
| HAVE_FCNTL_H |
| diff --git a/ncurses/tinfo/alloc_entry.c b/ncurses/tinfo/alloc_entry.c |
| index 5de09f1..09374d6 100644 |
| --- a/ncurses/tinfo/alloc_entry.c |
| +++ b/ncurses/tinfo/alloc_entry.c |
| @@ -47,7 +47,7 @@ |
| |
| #include <tic.h> |
| |
| -MODULE_ID("$Id: alloc_entry.c,v 1.60 2017/06/27 23:48:55 tom Exp $") |
| +MODULE_ID("$Id: alloc_entry.c,v 1.61 2017/08/25 09:09:08 tom Exp $") |
| |
| #define ABSENT_OFFSET -1 |
| #define CANCELLED_OFFSET -2 |
| @@ -98,7 +98,7 @@ _nc_save_str(const char *const string) |
| size_t old_next_free = next_free; |
| size_t len; |
| |
| - if (string == 0) |
| + if (!VALID_STRING(string)) |
| return _nc_save_str(""); |
| len = strlen(string) + 1; |
| |
| diff --git a/ncurses/tinfo/comp_parse.c b/ncurses/tinfo/comp_parse.c |
| index 34e6216..580d4df 100644 |
| --- a/ncurses/tinfo/comp_parse.c |
| +++ b/ncurses/tinfo/comp_parse.c |
| @@ -47,7 +47,7 @@ |
| |
| #include <tic.h> |
| |
| -MODULE_ID("$Id: comp_parse.c,v 1.96 2017/04/15 15:36:58 tom Exp $") |
| +MODULE_ID("$Id: comp_parse.c,v 1.99 2017/08/26 16:15:50 tom Exp $") |
| |
| static void sanity_check2(TERMTYPE2 *, bool); |
| NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE2 *, bool) = sanity_check2; |
| @@ -510,9 +510,9 @@ static void |
| fixup_acsc(TERMTYPE2 *tp, int literal) |
| { |
| if (!literal) { |
| - if (acs_chars == 0 |
| - && enter_alt_charset_mode != 0 |
| - && exit_alt_charset_mode != 0) |
| + if (acs_chars == ABSENT_STRING |
| + && PRESENT(enter_alt_charset_mode) |
| + && PRESENT(exit_alt_charset_mode)) |
| acs_chars = strdup(VT_ACSC); |
| } |
| } |
| @@ -568,9 +568,7 @@ sanity_check2(TERMTYPE2 *tp, bool literal) |
| PAIRED(enter_xon_mode, exit_xon_mode); |
| PAIRED(enter_am_mode, exit_am_mode); |
| ANDMISSING(label_off, label_on); |
| -#ifdef remove_clock |
| PAIRED(display_clock, remove_clock); |
| -#endif |
| ANDMISSING(set_color_pair, initialize_pair); |
| } |
| |
| diff --git a/ncurses/tinfo/comp_scan.c b/ncurses/tinfo/comp_scan.c |
| index 40d7f6a..b207257 100644 |
| --- a/ncurses/tinfo/comp_scan.c |
| +++ b/ncurses/tinfo/comp_scan.c |
| @@ -50,7 +50,7 @@ |
| #include <ctype.h> |
| #include <tic.h> |
| |
| -MODULE_ID("$Id: comp_scan.c,v 1.106 2017/04/22 11:41:12 tom Exp $") |
| +MODULE_ID("$Id: comp_scan.c,v 1.108 2017/08/25 22:57:21 tom Exp $") |
| |
| /* |
| * Maximum length of string capability we'll accept before raising an error. |
| @@ -168,6 +168,8 @@ next_char(void) |
| if (result != 0) { |
| FreeAndNull(result); |
| FreeAndNull(pushname); |
| + bufptr = 0; |
| + bufstart = 0; |
| allocated = 0; |
| } |
| /* |
| @@ -222,6 +224,8 @@ next_char(void) |
| } |
| if ((bufptr = bufstart) != 0) { |
| used = strlen(bufptr); |
| + if (used == 0) |
| + return (EOF); |
| while (iswhite(*bufptr)) { |
| if (*bufptr == '\t') { |
| _nc_curr_col = (_nc_curr_col | 7) + 1; |
| diff --git a/ncurses/tinfo/parse_entry.c b/ncurses/tinfo/parse_entry.c |
| index 3fa2f25..bbbfcb2 100644 |
| --- a/ncurses/tinfo/parse_entry.c |
| +++ b/ncurses/tinfo/parse_entry.c |
| @@ -47,7 +47,7 @@ |
| #include <ctype.h> |
| #include <tic.h> |
| |
| -MODULE_ID("$Id: parse_entry.c,v 1.86 2017/06/28 00:53:12 tom Exp $") |
| +MODULE_ID("$Id: parse_entry.c,v 1.91 2017/08/26 16:13:34 tom Exp $") |
| |
| #ifdef LINT |
| static short const parametrized[] = |
| @@ -180,6 +180,20 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type) |
| } |
| #endif /* NCURSES_XNAMES */ |
| |
| +static bool |
| +valid_entryname(const char *name) |
| +{ |
| + bool result = TRUE; |
| + int ch; |
| + while ((ch = UChar(*name++)) != '\0') { |
| + if (ch <= ' ' || ch > '~' || ch == '/') { |
| + result = FALSE; |
| + break; |
| + } |
| + } |
| + return result; |
| +} |
| + |
| /* |
| * int |
| * _nc_parse_entry(entry, literal, silent) |
| @@ -211,6 +225,7 @@ _nc_parse_entry(ENTRY * entryp, int literal, bool silent) |
| int token_type; |
| struct name_table_entry const *entry_ptr; |
| char *ptr, *base; |
| + const char *name; |
| bool bad_tc_usage = FALSE; |
| |
| token_type = _nc_get_token(silent); |
| @@ -261,7 +276,12 @@ _nc_parse_entry(ENTRY * entryp, int literal, bool silent) |
| * results in the terminal type getting prematurely set to correspond |
| * to that of the next entry. |
| */ |
| - _nc_set_type(_nc_first_name(entryp->tterm.term_names)); |
| + name = _nc_first_name(entryp->tterm.term_names); |
| + if (!valid_entryname(name)) { |
| + _nc_warning("invalid entry name \"%s\"", name); |
| + name = "invalid"; |
| + } |
| + _nc_set_type(name); |
| |
| /* check for overly-long names and aliases */ |
| for (base = entryp->tterm.term_names; (ptr = strchr(base, '|')) != 0; |
| @@ -283,13 +303,24 @@ _nc_parse_entry(ENTRY * entryp, int literal, bool silent) |
| bool is_use = (strcmp(_nc_curr_token.tk_name, "use") == 0); |
| bool is_tc = !is_use && (strcmp(_nc_curr_token.tk_name, "tc") == 0); |
| if (is_use || is_tc) { |
| + if (!VALID_STRING(_nc_curr_token.tk_valstring) |
| + || _nc_curr_token.tk_valstring[0] == '\0') { |
| + _nc_warning("missing name for use-clause"); |
| + continue; |
| + } else if (!valid_entryname(_nc_curr_token.tk_valstring)) { |
| + _nc_warning("invalid name for use-clause \"%s\"", |
| + _nc_curr_token.tk_valstring); |
| + continue; |
| + } else if (entryp->nuses >= MAX_USES) { |
| + _nc_warning("too many use-clauses, ignored \"%s\"", |
| + _nc_curr_token.tk_valstring); |
| + continue; |
| + } |
| entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring); |
| entryp->uses[entryp->nuses].line = _nc_curr_line; |
| - if (VALID_STRING(entryp->uses[entryp->nuses].name)) { |
| - entryp->nuses++; |
| - if (entryp->nuses > 1 && is_tc) { |
| - BAD_TC_USAGE |
| - } |
| + entryp->nuses++; |
| + if (entryp->nuses > 1 && is_tc) { |
| + BAD_TC_USAGE |
| } |
| } else { |
| /* normal token lookup */ |
| @@ -641,13 +672,6 @@ static const char C_BS[] = "\b"; |
| static const char C_HT[] = "\t"; |
| |
| /* |
| - * Note that WANTED and PRESENT are not simple inverses! If a capability |
| - * has been explicitly cancelled, it's not considered WANTED. |
| - */ |
| -#define WANTED(s) ((s) == ABSENT_STRING) |
| -#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING)) |
| - |
| -/* |
| * This bit of legerdemain turns all the terminfo variable names into |
| * references to locations in the arrays Booleans, Numbers, and Strings --- |
| * precisely what's needed. |
| @@ -672,10 +696,10 @@ postprocess_termcap(TERMTYPE2 *tp, bool has_base) |
| |
| /* if there was a tc entry, assume we picked up defaults via that */ |
| if (!has_base) { |
| - if (WANTED(init_3string) && termcap_init2) |
| + if (WANTED(init_3string) && PRESENT(termcap_init2)) |
| init_3string = _nc_save_str(termcap_init2); |
| |
| - if (WANTED(reset_2string) && termcap_reset) |
| + if (WANTED(reset_2string) && PRESENT(termcap_reset)) |
| reset_2string = _nc_save_str(termcap_reset); |
| |
| if (WANTED(carriage_return)) { |
| @@ -790,7 +814,7 @@ postprocess_termcap(TERMTYPE2 *tp, bool has_base) |
| if (init_tabs != 8 && init_tabs != ABSENT_NUMERIC) |
| _nc_warning("hardware tabs with a width other than 8: %d", init_tabs); |
| else { |
| - if (tab && _nc_capcmp(tab, C_HT)) |
| + if (PRESENT(tab) && _nc_capcmp(tab, C_HT)) |
| _nc_warning("hardware tabs with a non-^I tab string %s", |
| _nc_visbuf(tab)); |
| else { |
| @@ -867,17 +891,22 @@ postprocess_termcap(TERMTYPE2 *tp, bool has_base) |
| * The magic moment -- copy the mapped key string over, |
| * stripping out padding. |
| */ |
| - for (dp = buf2, bp = tp->Strings[from_ptr->nte_index]; *bp; bp++) { |
| - if (bp[0] == '$' && bp[1] == '<') { |
| - while (*bp && *bp != '>') { |
| - ++bp; |
| - } |
| - } else |
| - *dp++ = *bp; |
| - } |
| - *dp = '\0'; |
| + bp = tp->Strings[from_ptr->nte_index]; |
| + if (VALID_STRING(bp)) { |
| + for (dp = buf2; *bp; bp++) { |
| + if (bp[0] == '$' && bp[1] == '<') { |
| + while (*bp && *bp != '>') { |
| + ++bp; |
| + } |
| + } else |
| + *dp++ = *bp; |
| + } |
| + *dp = '\0'; |
| |
| - tp->Strings[to_ptr->nte_index] = _nc_save_str(buf2); |
| + tp->Strings[to_ptr->nte_index] = _nc_save_str(buf2); |
| + } else { |
| + tp->Strings[to_ptr->nte_index] = bp; |
| + } |
| } |
| |
| /* |
| @@ -886,7 +915,7 @@ postprocess_termcap(TERMTYPE2 *tp, bool has_base) |
| * got mapped to kich1 and im to kIC to avoid a collision. |
| * If the description has im but not ic, hack kIC back to kich1. |
| */ |
| - if (foundim && WANTED(key_ic) && key_sic) { |
| + if (foundim && WANTED(key_ic) && PRESENT(key_sic)) { |
| key_ic = key_sic; |
| key_sic = ABSENT_STRING; |
| } |
| @@ -938,9 +967,9 @@ postprocess_termcap(TERMTYPE2 *tp, bool has_base) |
| acs_chars = _nc_save_str(buf2); |
| _nc_warning("acsc string synthesized from XENIX capabilities"); |
| } |
| - } else if (acs_chars == 0 |
| - && enter_alt_charset_mode != 0 |
| - && exit_alt_charset_mode != 0) { |
| + } else if (acs_chars == ABSENT_STRING |
| + && PRESENT(enter_alt_charset_mode) |
| + && PRESENT(exit_alt_charset_mode)) { |
| acs_chars = _nc_save_str(VT_ACSC); |
| } |
| } |
| diff --git a/ncurses/tinfo/strings.c b/ncurses/tinfo/strings.c |
| index 393d8e7..10ec6c8 100644 |
| --- a/ncurses/tinfo/strings.c |
| +++ b/ncurses/tinfo/strings.c |
| @@ -1,5 +1,5 @@ |
| /**************************************************************************** |
| - * Copyright (c) 2000-2007,2012 Free Software Foundation, Inc. * |
| + * Copyright (c) 2000-2012,2017 Free Software Foundation, Inc. * |
| * * |
| * Permission is hereby granted, free of charge, to any person obtaining a * |
| * copy of this software and associated documentation files (the * |
| @@ -35,8 +35,9 @@ |
| **/ |
| |
| #include <curses.priv.h> |
| +#include <tic.h> |
| |
| -MODULE_ID("$Id: strings.c,v 1.8 2012/02/22 22:34:31 tom Exp $") |
| +MODULE_ID("$Id: strings.c,v 1.9 2017/08/26 13:16:11 tom Exp $") |
| |
| /**************************************************************************** |
| * Useful string functions (especially for mvcur) |
| @@ -105,7 +106,7 @@ _nc_str_copy(string_desc * dst, string_desc * src) |
| NCURSES_EXPORT(bool) |
| _nc_safe_strcat(string_desc * dst, const char *src) |
| { |
| - if (src != 0) { |
| + if (PRESENT(src)) { |
| size_t len = strlen(src); |
| |
| if (len < dst->s_size) { |
| @@ -126,7 +127,7 @@ _nc_safe_strcat(string_desc * dst, const char *src) |
| NCURSES_EXPORT(bool) |
| _nc_safe_strcpy(string_desc * dst, const char *src) |
| { |
| - if (src != 0) { |
| + if (PRESENT(src)) { |
| size_t len = strlen(src); |
| |
| if (len < dst->s_size) { |
| diff --git a/ncurses/tinfo/trim_sgr0.c b/ncurses/tinfo/trim_sgr0.c |
| index 4cbcb65..4d92d15 100644 |
| --- a/ncurses/tinfo/trim_sgr0.c |
| +++ b/ncurses/tinfo/trim_sgr0.c |
| @@ -36,7 +36,7 @@ |
| |
| #include <tic.h> |
| |
| -MODULE_ID("$Id: trim_sgr0.c,v 1.16 2017/04/05 22:33:07 tom Exp $") |
| +MODULE_ID("$Id: trim_sgr0.c,v 1.17 2017/08/26 14:54:16 tom Exp $") |
| |
| #undef CUR |
| #define CUR tp-> |
| @@ -263,7 +263,7 @@ _nc_trim_sgr0(TERMTYPE2 *tp) |
| /* |
| * If rmacs is a substring of sgr(0), remove that chunk. |
| */ |
| - if (exit_alt_charset_mode != 0) { |
| + if (PRESENT(exit_alt_charset_mode)) { |
| TR(TRACE_DATABASE, ("scan for rmacs %s", _nc_visbuf(exit_alt_charset_mode))); |
| j = strlen(off); |
| k = strlen(exit_alt_charset_mode); |
| diff --git a/progs/tic.c b/progs/tic.c |
| index c5d78e5..6dd4678 100644 |
| --- a/progs/tic.c |
| +++ b/progs/tic.c |
| @@ -48,7 +48,7 @@ |
| #include <parametrized.h> |
| #include <transform.h> |
| |
| -MODULE_ID("$Id: tic.c,v 1.233 2017/07/15 17:40:19 tom Exp $") |
| +MODULE_ID("$Id: tic.c,v 1.243 2017/08/26 20:56:55 tom Exp $") |
| |
| #define STDIN_NAME "<stdin>" |
| |
| @@ -62,6 +62,10 @@ static bool showsummary = FALSE; |
| static char **namelst = 0; |
| static const char *to_remove; |
| |
| +#if NCURSES_XNAMES |
| +static bool using_extensions = FALSE; |
| +#endif |
| + |
| static void (*save_check_termtype) (TERMTYPE2 *, bool); |
| static void check_termtype(TERMTYPE2 *tt, bool); |
| |
| @@ -850,6 +854,7 @@ main(int argc, char *argv[]) |
| /* FALLTHRU */ |
| case 'x': |
| use_extended_names(TRUE); |
| + using_extensions = TRUE; |
| break; |
| #endif |
| default: |
| @@ -2405,10 +2410,17 @@ check_conflict(TERMTYPE2 *tp) |
| const char *a = given[j].value; |
| bool first = TRUE; |
| |
| + if (!VALID_STRING(a)) |
| + continue; |
| + |
| for (k = j + 1; given[k].keycode; k++) { |
| const char *b = given[k].value; |
| + |
| + if (!VALID_STRING(b)) |
| + continue; |
| if (check[k]) |
| continue; |
| + |
| if (!_nc_capcmp(a, b)) { |
| check[j] = 1; |
| check[k] = 1; |
| @@ -2431,6 +2443,67 @@ check_conflict(TERMTYPE2 *tp) |
| if (!first) |
| fprintf(stderr, "\n"); |
| } |
| +#if NCURSES_XNAMES |
| + if (using_extensions) { |
| + /* *INDENT-OFF* */ |
| + static struct { |
| + const char *xcurses; |
| + const char *shifted; |
| + } table[] = { |
| + { "kDC", NULL }, |
| + { "kDN", "kind" }, |
| + { "kEND", NULL }, |
| + { "kHOM", NULL }, |
| + { "kLFT", NULL }, |
| + { "kNXT", NULL }, |
| + { "kPRV", NULL }, |
| + { "kRIT", NULL }, |
| + { "kUP", "kri" }, |
| + { NULL, NULL }, |
| + }; |
| + /* *INDENT-ON* */ |
| + |
| + /* |
| + * SVr4 curses defines the "xcurses" names listed above except for |
| + * the special cases in the "shifted" column. When using these |
| + * names for xterm's extensions, that was confusing, and resulted |
| + * in adding extended capabilities with "2" (shift) suffix. This |
| + * check warns about unnecessary use of extensions for this quirk. |
| + */ |
| + for (j = 0; given[j].keycode; ++j) { |
| + const char *find = given[j].name; |
| + int value; |
| + char ch; |
| + |
| + if (!VALID_STRING(given[j].value)) |
| + continue; |
| + |
| + for (k = 0; table[k].xcurses; ++k) { |
| + const char *test = table[k].xcurses; |
| + size_t size = strlen(test); |
| + |
| + if (!strncmp(find, test, size) && strcmp(find, test)) { |
| + switch (sscanf(find + size, "%d%c", &value, &ch)) { |
| + case 1: |
| + if (value == 2) { |
| + _nc_warning("expected '%s' rather than '%s'", |
| + (table[k].shifted |
| + ? table[k].shifted |
| + : test), find); |
| + } else if (value < 2 || value > 15) { |
| + _nc_warning("expected numeric 2..15 '%s'", find); |
| + } |
| + break; |
| + default: |
| + _nc_warning("expected numeric suffix for '%s'", find); |
| + break; |
| + } |
| + break; |
| + } |
| + } |
| + } |
| + } |
| +#endif |
| free(given); |
| free(check); |
| } |
| -- |
| 2.10.2 |
| |