Bug#867817: jessie-pu: package ncurses/5.9+20140913-1+deb8u1
- To: "Adam D. Barratt" <adam@adam-barratt.org.uk>
- Cc: 867817@bugs.debian.org
- Subject: Bug#867817: jessie-pu: package ncurses/5.9+20140913-1+deb8u1
- From: Sven Joachim <svenjoac@gmx.de>
- Date: Wed, 06 Sep 2017 19:02:00 +0200
- Message-id: <[🔎] 87fubzhibb.fsf@turtle.gmx.de>
- Reply-to: Sven Joachim <svenjoac@gmx.de>, 867817@bugs.debian.org
- In-reply-to: <87bmnk1yy8.fsf@turtle.gmx.de> (Sven Joachim's message of "Sat, 12 Aug 2017 19:24:31 +0200")
- References: <874lulcxul.fsf@turtle.gmx.de> <1500115114.5317.196.camel@adam-barratt.org.uk> <87y3rqezsn.fsf@turtle.gmx.de> <874lulcxul.fsf@turtle.gmx.de> <87bmnk1yy8.fsf@turtle.gmx.de> <874lulcxul.fsf@turtle.gmx.de>
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: