[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#867817: jessie-pu: package ncurses/5.9+20140913-1+deb8u1



On 2017-08-12 19:24 +0200, Sven Joachim wrote:

> Control: tags -1 - moreinfo
>
> On 2017-07-15 12:54 +0200, Sven Joachim wrote:
>
>> On 2017-07-15 11:38 +0100, Adam D. Barratt wrote:
>>
>>> Control: tags -1 + confirmed
>>>
>>> On Sun, 2017-07-09 at 19:40 +0200, Sven Joachim wrote:
>>>> The same problem as in #867814 for stretch and almost the same fix,
>>>> except that one inapplicable hunk has been removed from the patch.
>>>
>>> Please go ahead.
>>
>> Same answer as in #867814, the fallout from #868266 needs to be sorted
>> out first → no upload this weekend, defer for 8.10.
>
> Unfortunately the fixes from the 20170715 patchlevel were rather large
> and not easily backportable to jessie, but finally openSUSE[1] has come
> up with a patch that I have stolen.  The output of "infocmp -C" slightly
> differs from the one in currently in jessie, but I think there are no
> functional differences.  At least perldoc works fine.

As in #867814, I would like to fix the seven new CVEs 2017-137{28..34}
as well.  The two additional patches are the same as the ones for
stretch (modulo line numbers, since I ran "quilt refresh").

Cheers,
       Sven

diff -Nru ncurses-5.9+20140913/debian/changelog ncurses-5.9+20140913/debian/changelog
--- ncurses-5.9+20140913/debian/changelog	2014-09-17 19:00:57.000000000 +0200
+++ ncurses-5.9+20140913/debian/changelog	2017-09-06 17:11:59.000000000 +0200
@@ -1,3 +1,18 @@
+ncurses (5.9+20140913-1+deb8u1) jessie; urgency=medium
+
+  * Cherry-pick upstream fixes from the 20170701 and 20170708 patchlevels
+    for various crash bugs in the tic library and the tic binary
+    (CVE-2017-10684, CVE-2017-10685, CVE-2017-11112, CVE-2017-11113).
+  * Apply termcap-format fix from openSUSE's ncurses-5.9-55.6.1 package,
+    repairing a regression from the above security fixes (see #868266).
+  * Cherry-pick upstream fixes from the 20170826 patchlevel for more
+    crash bugs in the tic library (CVE-2017-13728, CVE-2017-13729,
+    CVE-2017-13730, CVE-2017-13731, CVE-2017-13732, CVE-2017-13734).
+  * Cerry-pick upstream fixes from the 20170902 patchlevel to fix
+    another crash bug in the tic program (CVE-2017-13733).
+
+ -- Sven Joachim <svenjoac@gmx.de>  Wed, 06 Sep 2017 17:11:59 +0200
+
 ncurses (5.9+20140913-1) unstable; urgency=low
 
   * New upstream patchlevel.
diff -Nru ncurses-5.9+20140913/debian/patches/cve-2017-13733.diff ncurses-5.9+20140913/debian/patches/cve-2017-13733.diff
--- ncurses-5.9+20140913/debian/patches/cve-2017-13733.diff	1970-01-01 01:00:00.000000000 +0100
+++ ncurses-5.9+20140913/debian/patches/cve-2017-13733.diff	2017-09-06 17:11:59.000000000 +0200
@@ -0,0 +1,91 @@
+Author: Sven Joachim <svenjoac@gmx.de>
+Description: Fix for CVE-2017-13733 in the tic program
+ Fix for CVE-2017-13733 cherry-picked from upstream patchlevel
+ 20170902.
+Bug-Debian: https://bugs.debian.org/873746
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1484290
+Forwarded: not-needed
+Last-Update: 2017-09-06
+
+---
+ progs/dump_entry.c |   19 ++++++++++---------
+ progs/tput.c       |    2 +-
+ 2 files changed, 11 insertions(+), 10 deletions(-)
+
+--- a/progs/dump_entry.c
++++ b/progs/dump_entry.c
+@@ -722,12 +722,12 @@ fmt_entry(TERMTYPE *tterm,
+ #undef CUR
+ #define CUR tterm->
+     if (outform == F_TERMCAP) {
+-	if (termcap_reset != ABSENT_STRING) {
+-	    if (init_3string != ABSENT_STRING
++	if (VALID_STRING(termcap_reset)) {
++	    if (VALID_STRING(init_3string)
+ 		&& !strcmp(init_3string, termcap_reset))
+ 		DISCARD(init_3string);
+ 
+-	    if (reset_2string != ABSENT_STRING
++	    if (VALID_STRING(reset_2string)
+ 		&& !strcmp(reset_2string, termcap_reset))
+ 		DISCARD(reset_2string);
+ 	}
+@@ -799,7 +799,7 @@ fmt_entry(TERMTYPE *tterm,
+ 	buffer[0] = '\0';
+ 
+ 	if (predval != FAIL) {
+-	    if (capability != ABSENT_STRING
++	    if (VALID_STRING(capability)
+ 		&& i + 1 > num_strings)
+ 		num_strings = i + 1;
+ 
+@@ -877,8 +877,7 @@ fmt_entry(TERMTYPE *tterm,
+ 	    }
+ 	}
+ 	/* e.g., trimmed_sgr0 */
+-	if (capability != ABSENT_STRING &&
+-	    capability != CANCELLED_STRING &&
++	if (VALID_STRING(capability) &&
+ 	    capability != tterm->Strings[i])
+ 	    free(capability);
+     }
+@@ -1047,7 +1046,8 @@ kill_labels(TERMTYPE *tterm, int target)
+ 
+     for (n = 0; n <= 10; ++n) {
+ 	_nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "lf%d", n);
+-	if ((cap = find_string(tterm, name)) != ABSENT_STRING
++	cap = find_string(tterm, name);
++	if (VALID_STRING(cap)
+ 	    && kill_string(tterm, cap)) {
+ 	    target -= (int) (strlen(cap) + 5);
+ 	    ++result;
+@@ -1072,7 +1072,8 @@ kill_fkeys(TERMTYPE *tterm, int target)
+ 
+     for (n = 60; n >= 0; --n) {
+ 	_nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "kf%d", n);
+-	if ((cap = find_string(tterm, name)) != ABSENT_STRING
++	cap = find_string(tterm, name);
++	if (VALID_STRING(cap)
+ 	    && kill_string(tterm, cap)) {
+ 	    target -= (int) (strlen(cap) + 5);
+ 	    ++result;
+@@ -1094,7 +1095,7 @@ one_one_mapping(const char *mapping)
+ {
+     bool result = TRUE;
+ 
+-    if (mapping != ABSENT_STRING) {
++    if (VALID_STRING(mapping)) {
+ 	int n = 0;
+ 	while (mapping[n] != '\0') {
+ 	    if (isLine(mapping[n]) &&
+--- a/progs/tput.c
++++ b/progs/tput.c
+@@ -261,7 +261,7 @@ tput(int argc, char *argv[])
+ 	}
+ #endif
+ 	quit(4, "unknown terminfo capability '%s'", name);
+-    } else if (s != ABSENT_STRING) {
++    } else if (VALID_STRING(s)) {
+ 	if (argc > 1) {
+ 	    int k;
+ 	    int ignored;
diff -Nru ncurses-5.9+20140913/debian/patches/cve-fixes.diff ncurses-5.9+20140913/debian/patches/cve-fixes.diff
--- ncurses-5.9+20140913/debian/patches/cve-fixes.diff	1970-01-01 01:00:00.000000000 +0100
+++ ncurses-5.9+20140913/debian/patches/cve-fixes.diff	2017-09-06 17:11:59.000000000 +0200
@@ -0,0 +1,173 @@
+Author: Sven Joachim <svenjoac@gmx.de>
+Description: Fixes for four CVEs
+ Fixes for CVE 2017-10684, CVE-2017-10685, CVE-2017-11112,
+ CVE-2017-11113 cherry-picked from upstream patchlevels 20170701 and
+ 20170708.
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1464684
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1464685
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1464686
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1464687
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1464691
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1464692
+Forwarded: not-needed
+Last-Update: 2017-07-09
+
+---
+ ncurses/tinfo/alloc_entry.c |    6 +++++-
+ ncurses/tinfo/parse_entry.c |   22 ++++++++++++----------
+ progs/dump_entry.c          |   30 +++++++++++++++++++-----------
+ 3 files changed, 36 insertions(+), 22 deletions(-)
+
+--- a/ncurses/tinfo/alloc_entry.c
++++ b/ncurses/tinfo/alloc_entry.c
+@@ -96,7 +96,11 @@ _nc_save_str(const char *const string)
+ {
+     char *result = 0;
+     size_t old_next_free = next_free;
+-    size_t len = strlen(string) + 1;
++    size_t len;
++
++    if (string == 0)
++	return _nc_save_str("");
++    len = strlen(string) + 1;
+ 
+     if (len == 1 && next_free != 0) {
+ 	/*
+--- a/ncurses/tinfo/parse_entry.c
++++ b/ncurses/tinfo/parse_entry.c
+@@ -236,13 +236,14 @@ _nc_parse_entry(struct entry *entryp, in
+      * implemented it.  Note that the resulting terminal type was never the
+      * 2-character name, but was instead the first alias after that.
+      */
++#define ok_TC2(s) (isgraph(UChar(s)) && (s) != '|')
+     ptr = _nc_curr_token.tk_name;
+     if (_nc_syntax == SYN_TERMCAP
+ #if NCURSES_XNAMES
+ 	&& !_nc_user_definable
+ #endif
+ 	) {
+-	if (ptr[2] == '|') {
++	if (ok_TC2(ptr[0]) && ok_TC2(ptr[1]) && (ptr[2] == '|')) {
+ 	    ptr += 3;
+ 	    _nc_curr_token.tk_name[2] = '\0';
+ 	}
+@@ -284,9 +285,11 @@ _nc_parse_entry(struct entry *entryp, in
+ 	if (is_use || is_tc) {
+ 	    entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring);
+ 	    entryp->uses[entryp->nuses].line = _nc_curr_line;
+-	    entryp->nuses++;
+-	    if (entryp->nuses > 1 && is_tc) {
+-		BAD_TC_USAGE
++	    if (VALID_STRING(entryp->uses[entryp->nuses].name)) {
++		entryp->nuses++;
++		if (entryp->nuses > 1 && is_tc) {
++		    BAD_TC_USAGE
++		}
+ 	    }
+ 	} else {
+ 	    /* normal token lookup */
+@@ -571,7 +574,7 @@ append_acs0(string_desc * dst, int code,
+ static void
+ append_acs(string_desc * dst, int code, char *src)
+ {
+-    if (src != 0 && strlen(src) == 1) {
++    if (VALID_STRING(src) && strlen(src) == 1) {
+ 	append_acs0(dst, code, *src);
+     }
+ }
+@@ -829,15 +832,14 @@ postprocess_termcap(TERMTYPE *tp, bool h
+ 	    }
+ 
+ 	    if (tp->Strings[to_ptr->nte_index]) {
++		const char *s = tp->Strings[from_ptr->nte_index];
++		const char *t = tp->Strings[to_ptr->nte_index];
+ 		/* There's no point in warning about it if it's the same
+ 		 * string; that's just an inefficiency.
+ 		 */
+-		if (strcmp(
+-			      tp->Strings[from_ptr->nte_index],
+-			      tp->Strings[to_ptr->nte_index]) != 0)
++		if (VALID_STRING(s) && VALID_STRING(t) && strcmp(s, t) != 0)
+ 		    _nc_warning("%s (%s) already has an explicit value %s, ignoring ko",
+-				ap->to, ap->from,
+-				_nc_visbuf(tp->Strings[to_ptr->nte_index]));
++				ap->to, ap->from, t);
+ 		continue;
+ 	    }
+ 
+--- a/progs/dump_entry.c
++++ b/progs/dump_entry.c
+@@ -609,9 +609,10 @@ fmt_entry(TERMTYPE *tterm,
+     PredIdx num_strings = 0;
+     bool outcount = 0;
+ 
+-#define WRAP_CONCAT	\
+-	wrap_concat(buffer); \
+-	outcount = TRUE
++#define WRAP_CONCAT1(s)		wrap_concat(s); outcount = TRUE
++#define WRAP_CONCAT2(a,b)	wrap_concat(a); WRAP_CONCAT1(b)
++#define WRAP_CONCAT3(a,b,c)	wrap_concat(a); WRAP_CONCAT2(b,c)
++#define WRAP_CONCAT		WRAP_CONCAT1(buffer)
+ 
+     len = 12;			/* terminfo file-header */
+ 
+@@ -802,13 +803,21 @@ fmt_entry(TERMTYPE *tterm,
+ 			_nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ 				    "%s=!!! %s WILL NOT CONVERT !!!",
+ 				    name, srccap);
++			WRAP_CONCAT;
+ 		    } else if (suppress_untranslatable) {
+ 			continue;
+ 		    } else {
+ 			char *s = srccap, *d = buffer;
+-			_nc_SPRINTF(d, _nc_SLIMIT(sizeof(buffer)) "..%s=", name);
+-			d += strlen(d);
++			WRAP_CONCAT3("..", name, "=");
+ 			while ((*d = *s++) != 0) {
++			    if ((d - buffer + 1) >= (int) sizeof(buffer)) {
++				fprintf(stderr,
++					"%s: value for %s is too long\n",
++					_nc_progname,
++					name);
++				*d = '\0';
++				break;
++			    }
+ 			    if (*d == ':') {
+ 				*d++ = '\\';
+ 				*d = ':';
+@@ -817,13 +826,12 @@ fmt_entry(TERMTYPE *tterm,
+ 			    }
+ 			    d++;
+ 			}
++			WRAP_CONCAT;
+ 		    }
+ 		} else {
+-		    _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+-				"%s=%s", name, cv);
++		    WRAP_CONCAT3(name, "=", cv);
+ 		}
+ 		len += (int) strlen(capability) + 1;
+-		WRAP_CONCAT;
+ 	    } else {
+ 		char *src = _nc_tic_expand(capability,
+ 					   outform == F_TERMINFO, numbers);
+@@ -839,8 +847,7 @@ fmt_entry(TERMTYPE *tterm,
+ 		    strcpy_DYN(&tmpbuf, src);
+ 		}
+ 		len += (int) strlen(capability) + 1;
+-		wrap_concat(tmpbuf.text);
+-		outcount = TRUE;
++		WRAP_CONCAT1(tmpbuf.text);
+ 	    }
+ 	}
+ 	/* e.g., trimmed_sgr0 */
+@@ -1203,7 +1210,8 @@ dump_entry(TERMTYPE *tterm,
+ 		}
+ 		if (len > critlen) {
+ 		    (void) fprintf(stderr,
+-				   "warning: %s entry is %d bytes long\n",
++				   "%s: %s entry is %d bytes long\n",
++				   _nc_progname,
+ 				   _nc_first_name(tterm->term_names),
+ 				   len);
+ 		    SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
diff -Nru ncurses-5.9+20140913/debian/patches/more-cve-fixes.diff ncurses-5.9+20140913/debian/patches/more-cve-fixes.diff
--- ncurses-5.9+20140913/debian/patches/more-cve-fixes.diff	1970-01-01 01:00:00.000000000 +0100
+++ ncurses-5.9+20140913/debian/patches/more-cve-fixes.diff	2017-09-06 17:11:59.000000000 +0200
@@ -0,0 +1,285 @@
+Author: Sven Joachim <svenjoac@gmx.de>
+Description: Fixes for six CVEs in the tic library
+ Fixes for CVE-2017-13728, CVE-2017-13729, CVE-2017-13730,
+ CVE-2017-13731, CVE-2017-13732 and CVE-2017-13734 cherry-picked from
+ upstream patchlevel 20170826.
+Bug-Debian: https://bugs.debian.org/873723
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1484274
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1484276
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1484284
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1484285
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1484287
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1484291
+Forwarded: not-needed
+Last-Update: 2017-09-06
+
+---
+ ncurses/tinfo/alloc_entry.c |    2 
+ ncurses/tinfo/comp_parse.c  |    8 +--
+ ncurses/tinfo/comp_scan.c   |    4 +
+ ncurses/tinfo/parse_entry.c |   89 +++++++++++++++++++++++++++++---------------
+ ncurses/tinfo/strings.c     |    5 +-
+ ncurses/tinfo/trim_sgr0.c   |    2 
+ 6 files changed, 71 insertions(+), 39 deletions(-)
+
+--- a/ncurses/tinfo/alloc_entry.c
++++ b/ncurses/tinfo/alloc_entry.c
+@@ -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;
+ 
+--- a/ncurses/tinfo/comp_parse.c
++++ b/ncurses/tinfo/comp_parse.c
+@@ -520,9 +520,9 @@ static void
+ fixup_acsc(TERMTYPE *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);
+     }
+ }
+@@ -578,9 +578,7 @@ sanity_check2(TERMTYPE *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);
+ }
+ 
+--- a/ncurses/tinfo/comp_scan.c
++++ b/ncurses/tinfo/comp_scan.c
+@@ -168,6 +168,8 @@ next_char(void)
+ 	if (result != 0) {
+ 	    FreeAndNull(result);
+ 	    FreeAndNull(pushname);
++	    bufptr = 0;
++	    bufstart = 0;
+ 	    allocated = 0;
+ 	}
+ 	/*
+@@ -223,6 +225,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;
+--- a/ncurses/tinfo/parse_entry.c
++++ b/ncurses/tinfo/parse_entry.c
+@@ -180,6 +180,20 @@ _nc_extend_names(ENTRY * entryp, char *n
+ }
+ #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(struct entry *entryp, in
+     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(struct entry *entryp, in
+      * 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(struct entry *entryp, in
+ 	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 */
+@@ -624,13 +655,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.
+@@ -655,10 +679,10 @@ postprocess_termcap(TERMTYPE *tp, bool h
+ 
+     /* 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)) {
+@@ -773,7 +797,7 @@ postprocess_termcap(TERMTYPE *tp, bool h
+ 	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 {
+@@ -847,17 +871,22 @@ postprocess_termcap(TERMTYPE *tp, bool h
+ 	     * 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;
++	    }
+ 	}
+ 
+ 	/*
+@@ -866,7 +895,7 @@ postprocess_termcap(TERMTYPE *tp, bool h
+ 	 * 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;
+ 	}
+@@ -918,9 +947,9 @@ postprocess_termcap(TERMTYPE *tp, bool h
+ 	    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);
+     }
+ }
+--- a/ncurses/tinfo/strings.c
++++ b/ncurses/tinfo/strings.c
+@@ -35,6 +35,7 @@
+ **/
+ 
+ #include <curses.priv.h>
++#include <tic.h>
+ 
+ MODULE_ID("$Id: strings.c,v 1.8 2012/02/22 22:34:31 tom Exp $")
+ 
+@@ -105,7 +106,7 @@ _nc_str_copy(string_desc * dst, string_d
+ 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
+ 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) {
+--- a/ncurses/tinfo/trim_sgr0.c
++++ b/ncurses/tinfo/trim_sgr0.c
+@@ -263,7 +263,7 @@ _nc_trim_sgr0(TERMTYPE *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 -Nru ncurses-5.9+20140913/debian/patches/series ncurses-5.9+20140913/debian/patches/series
--- ncurses-5.9+20140913/debian/patches/series	2014-09-15 20:01:33.000000000 +0200
+++ ncurses-5.9+20140913/debian/patches/series	2017-09-06 16:49:32.000000000 +0200
@@ -1,3 +1,7 @@
 01-debian-no-ada-doc.diff
 02-debian-backspace.diff
 03-debian-ncursesconfig-omit-L.diff
+cve-fixes.diff
+termcap-fix.diff
+more-cve-fixes.diff
+cve-2017-13733.diff
diff -Nru ncurses-5.9+20140913/debian/patches/termcap-fix.diff ncurses-5.9+20140913/debian/patches/termcap-fix.diff
--- ncurses-5.9+20140913/debian/patches/termcap-fix.diff	1970-01-01 01:00:00.000000000 +0100
+++ ncurses-5.9+20140913/debian/patches/termcap-fix.diff	2017-09-06 17:11:59.000000000 +0200
@@ -0,0 +1,63 @@
+Author: Sven Joachim <svenjoac@gmx.de>
+Description: Apply termcap-format fix from openSUSE
+Bug-Debian: https://bugs.debian.org/868266
+Forwarded: not-needed
+Last-Update: 2017-08-12
+
+---
+ progs/dump_entry.c |   30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+--- a/progs/dump_entry.c
++++ b/progs/dump_entry.c
+@@ -427,6 +427,22 @@ wrap_concat(const char *src)
+     column += (int) need;
+ }
+ 
++static void
++wrap_termap(const char *a, const char *b, const char *c)
++{
++    size_t need = strlen(a)+strlen(b)+strlen(c);
++    size_t want = strlen(separator)+need;
++    if (column > INDENT
++	&& column + (int) want > width) {
++	force_wrap();
++    }
++    strcpy_DYN(&outbuf, a);
++    strcpy_DYN(&outbuf, b);
++    strcpy_DYN(&outbuf, c);
++    strcpy_DYN(&outbuf, separator);
++    column += (int) need;
++}
++
+ #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
+ 	if ((size_t)(last - first) > sizeof(sep_trail)-1 \
+ 	 && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
+@@ -808,7 +824,12 @@ fmt_entry(TERMTYPE *tterm,
+ 			continue;
+ 		    } else {
+ 			char *s = srccap, *d = buffer;
+-			WRAP_CONCAT3("..", name, "=");
++			if (infodump) {
++			    WRAP_CONCAT3("..", name, "=");
++			} else {
++			    wrap_termap("..", name, "=");
++			    outcount = TRUE;
++			}
+ 			while ((*d = *s++) != 0) {
+ 			    if ((d - buffer + 1) >= (int) sizeof(buffer)) {
+ 				fprintf(stderr,
+@@ -829,7 +850,12 @@ fmt_entry(TERMTYPE *tterm,
+ 			WRAP_CONCAT;
+ 		    }
+ 		} else {
+-		    WRAP_CONCAT3(name, "=", cv);
++		    if (infodump) {
++			WRAP_CONCAT3(name, "=", cv);
++		    } else {
++			wrap_termap(name, "=", cv);
++			outcount = TRUE;
++		    }
+ 		}
+ 		len += (int) strlen(capability) + 1;
+ 	    } else {

Reply to: