Sun Mar 29 21:46:23 2020 UTC ()
terminfo: Promote a terminfo description to v3 when required

Blindly scanning the capabilities for # and checking that the following
number is bigger than a short isn't reliable because this could be a
string value:

SomeString#1234

Instead, if we process the numeric as normal and if it's value is too big
for v1 then promote the record to v3.


(roy)
diff -r1.21 -r1.22 src/lib/libterminfo/compile.c
diff -r1.17 -r1.18 src/lib/libterminfo/term_private.h

cvs diff -r1.21 -r1.22 src/lib/libterminfo/compile.c (expand / switch to unified diff)

--- src/lib/libterminfo/compile.c 2020/03/29 18:54:57 1.21
+++ src/lib/libterminfo/compile.c 2020/03/29 21:46:22 1.22
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: compile.c,v 1.21 2020/03/29 18:54:57 roy Exp $ */ 1/* $NetBSD: compile.c,v 1.22 2020/03/29 21:46:22 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009, 2010, 2011, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009, 2010, 2011, 2020 The NetBSD Foundation, Inc.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Roy Marples. 7 * by Roy Marples.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -22,27 +22,27 @@ @@ -22,27 +22,27 @@
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30#if HAVE_NBTOOL_CONFIG_H 30#if HAVE_NBTOOL_CONFIG_H
31#include "nbtool_config.h" 31#include "nbtool_config.h"
32#endif 32#endif
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35__RCSID("$NetBSD: compile.c,v 1.21 2020/03/29 18:54:57 roy Exp $"); 35__RCSID("$NetBSD: compile.c,v 1.22 2020/03/29 21:46:22 roy Exp $");
36 36
37#if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H 37#if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H
38#include <sys/endian.h> 38#include <sys/endian.h>
39#endif 39#endif
40 40
41#include <assert.h> 41#include <assert.h>
42#include <ctype.h> 42#include <ctype.h>
43#include <err.h> 43#include <err.h>
44#include <errno.h> 44#include <errno.h>
45#include <limits.h> 45#include <limits.h>
46#include <stdarg.h> 46#include <stdarg.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <stdint.h> 48#include <stdint.h>
@@ -54,26 +54,104 @@ __RCSID("$NetBSD: compile.c,v 1.21 2020/ @@ -54,26 +54,104 @@ __RCSID("$NetBSD: compile.c,v 1.21 2020/
54static void __printflike(2, 3) 54static void __printflike(2, 3)
55dowarn(int flags, const char *fmt, ...) 55dowarn(int flags, const char *fmt, ...)
56{ 56{
57 va_list va; 57 va_list va;
58 58
59 errno = EINVAL; 59 errno = EINVAL;
60 if (flags & TIC_WARNING) { 60 if (flags & TIC_WARNING) {
61 va_start(va, fmt); 61 va_start(va, fmt);
62 vwarnx(fmt, va); 62 vwarnx(fmt, va);
63 va_end(va); 63 va_end(va);
64 } 64 }
65} 65}
66 66
 67int
 68_ti_promote(TIC *tic)
 69{
 70 char *obuf, type, flag;
 71 const char *cap, *code, *str;
 72 size_t n, entries, strl;
 73 uint16_t ind;
 74 int num, ortype, error = 0;
 75
 76 ortype = tic->rtype;
 77 tic->rtype = TERMINFO_RTYPE;
 78 obuf = tic->name;
 79 tic->name = _ti_getname(tic->rtype, tic->name);
 80 if (tic->name == NULL) {
 81 warn("_ti_getname");
 82 tic->name = obuf;
 83 return -1;
 84 }
 85 free(obuf);
 86
 87 obuf = tic->nums.buf;
 88 cap = obuf;
 89 entries = tic->nums.entries;
 90 tic->nums.buf = NULL;
 91 tic->nums.entries = tic->nums.buflen = tic->nums.bufpos = 0;
 92 for (n = entries; n > 0; n--) {
 93 ind = _ti_decode_16(&cap);
 94 num = _ti_decode_num(&cap, ortype);
 95 if (VALID_NUMERIC(num) &&
 96 !_ti_encode_buf_id_num(&tic->nums, ind, num,
 97 _ti_numsize(tic)))
 98 {
 99 warn("promote num");
 100 error = -1;
 101 break;
 102 }
 103 }
 104 free(obuf);
 105
 106 obuf = tic->extras.buf;
 107 cap = obuf;
 108 entries = tic->extras.entries;
 109 tic->extras.buf = NULL;
 110 tic->extras.entries = tic->extras.buflen = tic->extras.bufpos = 0;
 111 for (n = entries; n > 0; n--) {
 112 num = _ti_decode_16(&cap);
 113 strl = 0;
 114 code = cap;
 115 cap += num;
 116 type = *cap++;
 117 switch (type) {
 118 case 'f':
 119 flag = *cap++;
 120 break;
 121 case 'n':
 122 num = _ti_decode_num(&cap, ortype);
 123 break;
 124 case 's':
 125 strl = _ti_decode_16(&cap);
 126 str = cap;
 127 cap += strl;
 128 break;
 129 default:
 130 errno = EINVAL;
 131 break;
 132 }
 133 if (!_ti_store_extra(tic, 0, code, type, flag, num,
 134 str, strl, TIC_EXTRA))
 135 {
 136 error = -1;
 137 break;
 138 }
 139 }
 140 free(obuf);
 141
 142 return error;
 143}
 144
67char * 145char *
68_ti_grow_tbuf(TBUF *tbuf, size_t len) 146_ti_grow_tbuf(TBUF *tbuf, size_t len)
69{ 147{
70 char *buf; 148 char *buf;
71 size_t l; 149 size_t l;
72 150
73 _DIAGASSERT(tbuf != NULL); 151 _DIAGASSERT(tbuf != NULL);
74 152
75 l = tbuf->bufpos + len; 153 l = tbuf->bufpos + len;
76 if (l > tbuf->buflen) { 154 if (l > tbuf->buflen) {
77 if (tbuf->buflen == 0) 155 if (tbuf->buflen == 0)
78 buf = malloc(l); 156 buf = malloc(l);
79 else 157 else
@@ -180,49 +258,61 @@ _ti_getname(int rtype, const char *orig) @@ -180,49 +258,61 @@ _ti_getname(int rtype, const char *orig)
180 name = malloc(diff + vlen + 1); 258 name = malloc(diff + vlen + 1);
181 if (name == NULL) 259 if (name == NULL)
182 return NULL; 260 return NULL;
183 261
184 memcpy(name, orig, diff); 262 memcpy(name, orig, diff);
185 memcpy(name + diff, verstr, vlen + 1); 263 memcpy(name + diff, verstr, vlen + 1);
186 return name; 264 return name;
187} 265}
188 266
189size_t 267size_t
190_ti_store_extra(TIC *tic, int wrn, const char *id, char type, char flag, 268_ti_store_extra(TIC *tic, int wrn, const char *id, char type, char flag,
191 int num, const char *str, size_t strl, int flags) 269 int num, const char *str, size_t strl, int flags)
192{ 270{
193 size_t l; 271 size_t l, capl;
194 272
195 _DIAGASSERT(tic != NULL); 273 _DIAGASSERT(tic != NULL);
196 274
197 if (strcmp(id, "use") != 0) { 275 if (strcmp(id, "use") != 0) {
198 if (_ti_find_extra(tic, &tic->extras, id) != NULL) 276 if (_ti_find_extra(tic, &tic->extras, id) != NULL)
199 return 0; 277 return 0;
200 if (!(flags & TIC_EXTRA)) { 278 if (!(flags & TIC_EXTRA)) {
201 if (wrn != 0) 279 if (wrn != 0)
202 dowarn(flags, "%s: %s: unknown capability", 280 dowarn(flags, "%s: %s: unknown capability",
203 tic->name, id); 281 tic->name, id);
204 return 0; 282 return 0;
205 } 283 }
206 } 284 }
207 285
208 l = strlen(id) + 1; 286 l = strlen(id) + 1;
209 if (l > UINT16_T_MAX) { 287 if (l > UINT16_MAX) {
210 dowarn(flags, "%s: %s: cap name is too long", tic->name, id); 288 dowarn(flags, "%s: %s: cap name is too long", tic->name, id);
211 return 0; 289 return 0;
212 } 290 }
213 291
214 if (!_ti_grow_tbuf(&tic->extras, 292 capl = sizeof(uint16_t) + l + 1;
215 l + strl + sizeof(uint16_t) + _ti_numsize(tic) + 1)) 293 switch (type) {
 294 case 'f':
 295 capl++;
 296 break;
 297 case 'n':
 298 capl += _ti_numsize(tic);
 299 break;
 300 case 's':
 301 capl += sizeof(uint16_t) + strl;
 302 break;
 303 }
 304
 305 if (!_ti_grow_tbuf(&tic->extras, capl))
216 return 0; 306 return 0;
217 _ti_encode_buf_count_str(&tic->extras, id, l); 307 _ti_encode_buf_count_str(&tic->extras, id, l);
218 tic->extras.buf[tic->extras.bufpos++] = type; 308 tic->extras.buf[tic->extras.bufpos++] = type;
219 switch (type) { 309 switch (type) {
220 case 'f': 310 case 'f':
221 tic->extras.buf[tic->extras.bufpos++] = flag; 311 tic->extras.buf[tic->extras.bufpos++] = flag;
222 break; 312 break;
223 case 'n': 313 case 'n':
224 _ti_encode_buf_num(&tic->extras, num, tic->rtype); 314 _ti_encode_buf_num(&tic->extras, num, tic->rtype);
225 break; 315 break;
226 case 's': 316 case 's':
227 _ti_encode_buf_count_str(&tic->extras, str, strl); 317 _ti_encode_buf_count_str(&tic->extras, str, strl);
228 break; 318 break;
@@ -423,39 +513,26 @@ _ti_get_token(char **cap, char sep) @@ -423,39 +513,26 @@ _ti_get_token(char **cap, char sep)
423 if (sep == ':' && esc == '\\' && **cap == 'E') 513 if (sep == ':' && esc == '\\' && **cap == 'E')
424 esc = 'x'; 514 esc = 'x';
425 else 515 else
426 esc = '\0'; 516 esc = '\0';
427 } 517 }
428 } 518 }
429 519
430 if (**cap != '\0') 520 if (**cap != '\0')
431 *(*cap)++ = '\0'; 521 *(*cap)++ = '\0';
432 522
433 return token; 523 return token;
434} 524}
435 525
436static int 
437_ti_find_rtype(const char *cap) 
438{ 
439 const char *ptr; 
440 
441 for (ptr = cap; (ptr = strchr(ptr, '#')) != NULL;) { 
442 if (strtol(++ptr, NULL, 0) > SHRT_MAX) { 
443 return TERMINFO_RTYPE; 
444 } 
445 } 
446 return TERMINFO_RTYPE_O1; 
447} 
448 
449int 526int
450_ti_encode_buf_id_num(TBUF *tbuf, int ind, int num, size_t len) 527_ti_encode_buf_id_num(TBUF *tbuf, int ind, int num, size_t len)
451{ 528{
452 if (!_ti_grow_tbuf(tbuf, sizeof(uint16_t) + len)) 529 if (!_ti_grow_tbuf(tbuf, sizeof(uint16_t) + len))
453 return 0; 530 return 0;
454 _ti_encode_buf_16(tbuf, ind); 531 _ti_encode_buf_16(tbuf, ind);
455 if (len == sizeof(uint32_t)) 532 if (len == sizeof(uint32_t))
456 _ti_encode_buf_32(tbuf, num); 533 _ti_encode_buf_32(tbuf, num);
457 else 534 else
458 _ti_encode_buf_16(tbuf, num); 535 _ti_encode_buf_16(tbuf, num);
459 tbuf->entries++; 536 tbuf->entries++;
460 return 1; 537 return 1;
461} 538}
@@ -515,28 +592,27 @@ _ti_compile(char *cap, int flags) @@ -515,28 +592,27 @@ _ti_compile(char *cap, int flags)
515 if (desc != NULL && strlen(desc) > UINT16_MAX - 1) { 592 if (desc != NULL && strlen(desc) > UINT16_MAX - 1) {
516 dowarn(flags, "%s: description too long: %s", name, desc); 593 dowarn(flags, "%s: description too long: %s", name, desc);
517 return NULL; 594 return NULL;
518 } 595 }
519 if (alias != NULL && strlen(alias) > UINT16_MAX - 1) { 596 if (alias != NULL && strlen(alias) > UINT16_MAX - 1) {
520 dowarn(flags, "%s: alias too long: %s", name, alias); 597 dowarn(flags, "%s: alias too long: %s", name, alias);
521 return NULL; 598 return NULL;
522 } 599 }
523 600
524 tic = calloc(sizeof(*tic), 1); 601 tic = calloc(sizeof(*tic), 1);
525 if (tic == NULL) 602 if (tic == NULL)
526 return NULL; 603 return NULL;
527 604
528 tic->rtype = (flags & TIC_COMPAT_V1) ? TERMINFO_RTYPE_O1 : 605 tic->rtype = TERMINFO_RTYPE_O1; /* will promote if needed */
529 _ti_find_rtype(cap); 
530 buf.buf = NULL; 606 buf.buf = NULL;
531 buf.buflen = 0; 607 buf.buflen = 0;
532 608
533 tic->name = _ti_getname(tic->rtype, name); 609 tic->name = _ti_getname(tic->rtype, name);
534 if (tic->name == NULL) 610 if (tic->name == NULL)
535 goto error; 611 goto error;
536 if (alias != NULL && flags & TIC_ALIAS) { 612 if (alias != NULL && flags & TIC_ALIAS) {
537 tic->alias = _ti_getname(tic->rtype, alias); 613 tic->alias = _ti_getname(tic->rtype, alias);
538 if (tic->alias == NULL) 614 if (tic->alias == NULL)
539 goto error; 615 goto error;
540 } 616 }
541 if (desc != NULL && flags & TIC_DESCRIPTION) { 617 if (desc != NULL && flags & TIC_DESCRIPTION) {
542 tic->desc = strdup(desc); 618 tic->desc = strdup(desc);
@@ -608,26 +684,33 @@ _ti_compile(char *cap, int flags) @@ -608,26 +684,33 @@ _ti_compile(char *cap, int flags)
608 continue; 684 continue;
609 685
610 cnum = strtol(p, &e, 0); 686 cnum = strtol(p, &e, 0);
611 if (*e != '\0') { 687 if (*e != '\0') {
612 dowarn(flags, "%s: %s: not a number", 688 dowarn(flags, "%s: %s: not a number",
613 tic->name, token); 689 tic->name, token);
614 continue; 690 continue;
615 } 691 }
616 if (!VALID_NUMERIC(cnum) || cnum > INT32_MAX) { 692 if (!VALID_NUMERIC(cnum) || cnum > INT32_MAX) {
617 dowarn(flags, "%s: %s: number %ld out of range", 693 dowarn(flags, "%s: %s: number %ld out of range",
618 tic->name, token, cnum); 694 tic->name, token, cnum);
619 continue; 695 continue;
620 } 696 }
 697 if (cnum > INT16_MAX) {
 698 if (flags & TIC_COMPAT_V1)
 699 cnum = INT16_MAX;
 700 else if (tic->rtype == TERMINFO_RTYPE_O1)
 701 if (_ti_promote(tic) == -1)
 702 goto error;
 703 }
621 704
622 num = (int)cnum; 705 num = (int)cnum;
623 if (ind == -1) { 706 if (ind == -1) {
624 if (!_ti_store_extra(tic, 1, token, 'n', -1, 707 if (!_ti_store_extra(tic, 1, token, 'n', -1,
625 num, NULL, 0, flags)) 708 num, NULL, 0, flags))
626 goto error; 709 goto error;
627 } else { 710 } else {
628 if (!_ti_encode_buf_id_num(&tic->nums, 711 if (!_ti_encode_buf_id_num(&tic->nums,
629 ind, num, _ti_numsize(tic))) 712 ind, num, _ti_numsize(tic)))
630 goto error; 713 goto error;
631 } 714 }
632 continue; 715 continue;
633 } 716 }

cvs diff -r1.17 -r1.18 src/lib/libterminfo/term_private.h (expand / switch to unified diff)

--- src/lib/libterminfo/term_private.h 2020/03/29 18:54:57 1.17
+++ src/lib/libterminfo/term_private.h 2020/03/29 21:46:22 1.18
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: term_private.h,v 1.17 2020/03/29 18:54:57 roy Exp $ */ 1/* $NetBSD: term_private.h,v 1.18 2020/03/29 21:46:22 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2009, 2010, 2013, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009, 2010, 2013, 2020 The NetBSD Foundation, Inc.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Roy Marples. 7 * by Roy Marples.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -141,49 +141,48 @@ const char * _ti_flagid(ssize_t); @@ -141,49 +141,48 @@ const char * _ti_flagid(ssize_t);
141const char * _ti_numid(ssize_t); 141const char * _ti_numid(ssize_t);
142const char * _ti_strid(ssize_t); 142const char * _ti_strid(ssize_t);
143int _ti_getterm(TERMINAL *, const char *, int); 143int _ti_getterm(TERMINAL *, const char *, int);
144void _ti_setospeed(TERMINAL *); 144void _ti_setospeed(TERMINAL *);
145 145
146/* libterminfo can compile terminfo strings too */ 146/* libterminfo can compile terminfo strings too */
147#define TIC_WARNING (1 << 0) 147#define TIC_WARNING (1 << 0)
148#define TIC_DESCRIPTION (1 << 1) 148#define TIC_DESCRIPTION (1 << 1)
149#define TIC_ALIAS (1 << 2) 149#define TIC_ALIAS (1 << 2)
150#define TIC_COMMENT (1 << 3) 150#define TIC_COMMENT (1 << 3)
151#define TIC_EXTRA (1 << 4) 151#define TIC_EXTRA (1 << 4)
152#define TIC_COMPAT_V1 (1 << 5) 152#define TIC_COMPAT_V1 (1 << 5)
153 153
154#define UINT16_T_MAX 0xffff 
155 
156typedef struct { 154typedef struct {
157 char *buf; 155 char *buf;
158 size_t buflen; 156 size_t buflen;
159 size_t bufpos; 157 size_t bufpos;
160 size_t entries; 158 size_t entries;
161} TBUF; 159} TBUF;
162 160
163typedef struct { 161typedef struct {
164 char *name; 162 char *name;
165 char *alias; 163 char *alias;
166 char *desc; 164 char *desc;
167 int rtype; 165 int rtype;
168 TBUF flags; 166 TBUF flags;
169 TBUF nums; 167 TBUF nums;
170 TBUF strs; 168 TBUF strs;
171 TBUF extras; 169 TBUF extras;
172} TIC; 170} TIC;
173 171
174#define _ti_numsize(tic) \ 172#define _ti_numsize(tic) \
175 ((tic)->rtype == TERMINFO_RTYPE_O1 ? sizeof(uint16_t) : sizeof(uint32_t)) 173 ((tic)->rtype == TERMINFO_RTYPE_O1 ? sizeof(uint16_t) : sizeof(uint32_t))
176 174
 175int _ti_promote(TIC *);
177char *_ti_grow_tbuf(TBUF *, size_t); 176char *_ti_grow_tbuf(TBUF *, size_t);
178char *_ti_get_token(char **, char); 177char *_ti_get_token(char **, char);
179const char *_ti_find_cap(TIC *, TBUF *, char, short); 178const char *_ti_find_cap(TIC *, TBUF *, char, short);
180const char *_ti_find_extra(TIC *, TBUF *, const char *); 179const char *_ti_find_extra(TIC *, TBUF *, const char *);
181char *_ti_getname(int, const char *); 180char *_ti_getname(int, const char *);
182size_t _ti_store_extra(TIC *, int, const char *, char, char, int, 181size_t _ti_store_extra(TIC *, int, const char *, char, char, int,
183 const char *, size_t, int); 182 const char *, size_t, int);
184TIC *_ti_compile(char *, int); 183TIC *_ti_compile(char *, int);
185ssize_t _ti_flatten(uint8_t **, const TIC *); 184ssize_t _ti_flatten(uint8_t **, const TIC *);
186void _ti_freetic(TIC *); 185void _ti_freetic(TIC *);
187 186
188int _ti_encode_buf_id_num(TBUF *, int, int, size_t); 187int _ti_encode_buf_id_num(TBUF *, int, int, size_t);
189int _ti_encode_buf_id_count_str(TBUF *, int, const void *, size_t); 188int _ti_encode_buf_id_count_str(TBUF *, int, const void *, size_t);