Module Name: src Committed By: roy Date: Sun Mar 29 21:46:23 UTC 2020
Modified Files: src/lib/libterminfo: compile.c term_private.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/lib/libterminfo/compile.c cvs rdiff -u -r1.17 -r1.18 src/lib/libterminfo/term_private.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libterminfo/compile.c diff -u src/lib/libterminfo/compile.c:1.21 src/lib/libterminfo/compile.c:1.22 --- src/lib/libterminfo/compile.c:1.21 Sun Mar 29 18:54:57 2020 +++ src/lib/libterminfo/compile.c Sun Mar 29 21:46:22 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: compile.c,v 1.21 2020/03/29 18:54:57 roy Exp $ */ +/* $NetBSD: compile.c,v 1.22 2020/03/29 21:46:22 roy Exp $ */ /* * Copyright (c) 2009, 2010, 2011, 2020 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #endif #include <sys/cdefs.h> -__RCSID("$NetBSD: compile.c,v 1.21 2020/03/29 18:54:57 roy Exp $"); +__RCSID("$NetBSD: compile.c,v 1.22 2020/03/29 21:46:22 roy Exp $"); #if !HAVE_NBTOOL_CONFIG_H || HAVE_SYS_ENDIAN_H #include <sys/endian.h> @@ -64,6 +64,84 @@ dowarn(int flags, const char *fmt, ...) } } +int +_ti_promote(TIC *tic) +{ + char *obuf, type, flag; + const char *cap, *code, *str; + size_t n, entries, strl; + uint16_t ind; + int num, ortype, error = 0; + + ortype = tic->rtype; + tic->rtype = TERMINFO_RTYPE; + obuf = tic->name; + tic->name = _ti_getname(tic->rtype, tic->name); + if (tic->name == NULL) { + warn("_ti_getname"); + tic->name = obuf; + return -1; + } + free(obuf); + + obuf = tic->nums.buf; + cap = obuf; + entries = tic->nums.entries; + tic->nums.buf = NULL; + tic->nums.entries = tic->nums.buflen = tic->nums.bufpos = 0; + for (n = entries; n > 0; n--) { + ind = _ti_decode_16(&cap); + num = _ti_decode_num(&cap, ortype); + if (VALID_NUMERIC(num) && + !_ti_encode_buf_id_num(&tic->nums, ind, num, + _ti_numsize(tic))) + { + warn("promote num"); + error = -1; + break; + } + } + free(obuf); + + obuf = tic->extras.buf; + cap = obuf; + entries = tic->extras.entries; + tic->extras.buf = NULL; + tic->extras.entries = tic->extras.buflen = tic->extras.bufpos = 0; + for (n = entries; n > 0; n--) { + num = _ti_decode_16(&cap); + strl = 0; + code = cap; + cap += num; + type = *cap++; + switch (type) { + case 'f': + flag = *cap++; + break; + case 'n': + num = _ti_decode_num(&cap, ortype); + break; + case 's': + strl = _ti_decode_16(&cap); + str = cap; + cap += strl; + break; + default: + errno = EINVAL; + break; + } + if (!_ti_store_extra(tic, 0, code, type, flag, num, + str, strl, TIC_EXTRA)) + { + error = -1; + break; + } + } + free(obuf); + + return error; +} + char * _ti_grow_tbuf(TBUF *tbuf, size_t len) { @@ -190,7 +268,7 @@ size_t _ti_store_extra(TIC *tic, int wrn, const char *id, char type, char flag, int num, const char *str, size_t strl, int flags) { - size_t l; + size_t l, capl; _DIAGASSERT(tic != NULL); @@ -206,13 +284,25 @@ _ti_store_extra(TIC *tic, int wrn, const } l = strlen(id) + 1; - if (l > UINT16_T_MAX) { + if (l > UINT16_MAX) { dowarn(flags, "%s: %s: cap name is too long", tic->name, id); return 0; } - if (!_ti_grow_tbuf(&tic->extras, - l + strl + sizeof(uint16_t) + _ti_numsize(tic) + 1)) + capl = sizeof(uint16_t) + l + 1; + switch (type) { + case 'f': + capl++; + break; + case 'n': + capl += _ti_numsize(tic); + break; + case 's': + capl += sizeof(uint16_t) + strl; + break; + } + + if (!_ti_grow_tbuf(&tic->extras, capl)) return 0; _ti_encode_buf_count_str(&tic->extras, id, l); tic->extras.buf[tic->extras.bufpos++] = type; @@ -433,19 +523,6 @@ _ti_get_token(char **cap, char sep) return token; } -static int -_ti_find_rtype(const char *cap) -{ - const char *ptr; - - for (ptr = cap; (ptr = strchr(ptr, '#')) != NULL;) { - if (strtol(++ptr, NULL, 0) > SHRT_MAX) { - return TERMINFO_RTYPE; - } - } - return TERMINFO_RTYPE_O1; -} - int _ti_encode_buf_id_num(TBUF *tbuf, int ind, int num, size_t len) { @@ -525,8 +602,7 @@ _ti_compile(char *cap, int flags) if (tic == NULL) return NULL; - tic->rtype = (flags & TIC_COMPAT_V1) ? TERMINFO_RTYPE_O1 : - _ti_find_rtype(cap); + tic->rtype = TERMINFO_RTYPE_O1; /* will promote if needed */ buf.buf = NULL; buf.buflen = 0; @@ -618,6 +694,13 @@ _ti_compile(char *cap, int flags) tic->name, token, cnum); continue; } + if (cnum > INT16_MAX) { + if (flags & TIC_COMPAT_V1) + cnum = INT16_MAX; + else if (tic->rtype == TERMINFO_RTYPE_O1) + if (_ti_promote(tic) == -1) + goto error; + } num = (int)cnum; if (ind == -1) { Index: src/lib/libterminfo/term_private.h diff -u src/lib/libterminfo/term_private.h:1.17 src/lib/libterminfo/term_private.h:1.18 --- src/lib/libterminfo/term_private.h:1.17 Sun Mar 29 18:54:57 2020 +++ src/lib/libterminfo/term_private.h Sun Mar 29 21:46:22 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: term_private.h,v 1.17 2020/03/29 18:54:57 roy Exp $ */ +/* $NetBSD: term_private.h,v 1.18 2020/03/29 21:46:22 roy Exp $ */ /* * Copyright (c) 2009, 2010, 2013, 2020 The NetBSD Foundation, Inc. @@ -151,8 +151,6 @@ void _ti_setospeed(TERMINAL *); #define TIC_EXTRA (1 << 4) #define TIC_COMPAT_V1 (1 << 5) -#define UINT16_T_MAX 0xffff - typedef struct { char *buf; size_t buflen; @@ -174,6 +172,7 @@ typedef struct { #define _ti_numsize(tic) \ ((tic)->rtype == TERMINFO_RTYPE_O1 ? sizeof(uint16_t) : sizeof(uint32_t)) +int _ti_promote(TIC *); char *_ti_grow_tbuf(TBUF *, size_t); char *_ti_get_token(char **, char); const char *_ti_find_cap(TIC *, TBUF *, char, short);