diff options
| author | Mikael Magnusson <mikachu@gmail.com> | 2026-05-12 22:57:47 +0200 |
|---|---|---|
| committer | Mikael Magnusson <mikachu@gmail.com> | 2026-05-16 18:28:31 +0200 |
| commit | 458ce89509f8ddeadad3c2b3d5f19f73bfc37610 (patch) | |
| tree | a5969724a5ca2526b4cc8b75d34fc6f0f37c39d1 | |
| parent | 54563: stat, system: minor fixes (diff) | |
| download | zsh-458ce89509f8ddeadad3c2b3d5f19f73bfc37610.tar zsh-458ce89509f8ddeadad3c2b3d5f19f73bfc37610.tar.gz zsh-458ce89509f8ddeadad3c2b3d5f19f73bfc37610.tar.bz2 zsh-458ce89509f8ddeadad3c2b3d5f19f73bfc37610.tar.lz zsh-458ce89509f8ddeadad3c2b3d5f19f73bfc37610.tar.xz zsh-458ce89509f8ddeadad3c2b3d5f19f73bfc37610.tar.zst zsh-458ce89509f8ddeadad3c2b3d5f19f73bfc37610.zip | |
54564: termcap, terminfo: reset u, fix metafy confusion
Ideally, these should just be unmetafy()d and passed to ncurses, but the
reality is that ncurses will just segfault if we do that when the user
passes a non-ascii value.
% echo $terminfo[らしりれ]
zsh: segmentation fault
% echotc れりの
zsh: segmentation fault
The tparm values do seem to work fine with multibyte strings, so do
unmetafy() for those.
| -rw-r--r-- | ChangeLog | 3 | ||||
| -rw-r--r-- | Src/Modules/termcap.c | 39 | ||||
| -rw-r--r-- | Src/Modules/terminfo.c | 33 |
3 files changed, 52 insertions, 23 deletions
@@ -1,5 +1,8 @@ 2026-05-16 Mikael Magnusson <mikachu@gmail.com> + * 54564: Src/Modules/termcap.c, Src/Modules/terminfo.c: termcap, + terminfo: reset u, fix metafy confusion + * 54563: Src/Modules/stat.c, Src/Modules/system.c: stat, system: minor fixes diff --git a/Src/Modules/termcap.c b/Src/Modules/termcap.c index af4009a3a..fade8f151 100644 --- a/Src/Modules/termcap.c +++ b/Src/Modules/termcap.c @@ -51,7 +51,7 @@ static char *boolcodes[] = { /**/ static int -ztgetflag(char *s) +ztgetflag(const char *s) { char **b; @@ -82,11 +82,20 @@ bin_echotc(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) char *s, buf[2048], *t, *u; int num, argct; - s = *argv++; if (termflags & TERM_BAD) return 1; if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term())) return 1; + + s = *argv++; + for (t = s; *t; t++) { + /* ncurses helpfully just crashes if you pass it nonascii */ + if ((unsigned char)*t > 0x7f) { + zwarnnam(name, "no such capability: %s", s); + return 1; + } + } + /* if the specified termcap has a numeric value, display it */ if ((num = tgetnum(s)) != -1) { printf("%d\n", num); @@ -143,8 +152,9 @@ static struct builtin bintab[] = { static HashNode gettermcap(UNUSED(HashTable ht), const char *name) { - int len, num; - char *tcstr, buf[2048], *u, *nameu; + int num; + char *tcstr, buf[2048], *u; + const char *t; Param pm = NULL; /* This depends on the termcap stuff in init.c */ @@ -153,18 +163,21 @@ gettermcap(UNUSED(HashTable ht), const char *name) if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term())) return NULL; - - nameu = dupstring(name); - unmetafy(nameu, &len); + for (t = name; *t; t++) { + /* ncurses helpfully just crashes if you pass it nonascii */ + if ((unsigned char)*t > 0x7f) { + return NULL; + } + } pm = (Param) hcalloc(sizeof(struct param)); - pm->node.nam = nameu; + pm->node.nam = dupstring(name); pm->node.flags = PM_READONLY; u = buf; /* logic in the following cascade copied from echotc, above */ - if ((num = tgetnum(nameu)) != -1) { + if ((num = tgetnum(name)) != -1) { pm->gsu.i = &nullsetinteger_gsu; pm->u.val = num; pm->node.flags |= PM_INTEGER; @@ -172,7 +185,7 @@ gettermcap(UNUSED(HashTable ht), const char *name) } pm->gsu.s = &nullsetscalar_gsu; - switch (ztgetflag(nameu)) { + switch (ztgetflag(name)) { case -1: break; case 0: @@ -184,7 +197,7 @@ gettermcap(UNUSED(HashTable ht), const char *name) pm->node.flags |= PM_SCALAR; return &pm->node; } - if ((tcstr = tgetstr(nameu, &u)) != NULL && tcstr != (char *)-1) { + if ((tcstr = tgetstr(name, &u)) != NULL && tcstr != (char *)-1) { pm->u.str = dupstring(tcstr); pm->node.flags |= PM_SCALAR; } else { @@ -201,7 +214,7 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags) { Param pm = NULL; int num; - char **capcode, *tcstr, buf[2048], *u; + char **capcode, *tcstr, buf[2048]; #ifndef HAVE_NUMCODES static char *numcodes[] = { @@ -252,7 +265,6 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags) #endif pm = (Param) hcalloc(sizeof(struct param)); - u = buf; pm->node.flags = PM_READONLY | PM_SCALAR; pm->gsu.s = &nullsetscalar_gsu; @@ -286,6 +298,7 @@ scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags) zstrcodes #endif ; *capcode; capcode++) { + char *u = buf; if ((tcstr = (char *)tgetstr(*capcode,&u)) != NULL && tcstr != (char *)-1) { pm->u.str = dupstring(tcstr); diff --git a/Src/Modules/terminfo.c b/Src/Modules/terminfo.c index f9ab64fb3..7ce162e81 100644 --- a/Src/Modules/terminfo.c +++ b/Src/Modules/terminfo.c @@ -68,12 +68,20 @@ bin_echoti(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) long pars[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; char *strcap[] = { "pfkey", "pfloc", "pfx", "pln", "pfxl", NULL }; - s = *argv++; /* This depends on the termcap stuff in init.c */ if (termflags & TERM_BAD) return 1; if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term())) return 1; + + s = *argv++; + for (t = s; *t; t++) { + /* ncurses helpfully just crashes if you pass it nonascii */ + if ((unsigned char)*t > 0x7f) { + zwarnnam(name, "no such terminfo capability: %s", s); + return 1; + } + } /* if the specified capability has a numeric value, display it */ if (((num = tigetnum(s)) != -1) && (num != -2)) { printf("%d\n", num); @@ -111,7 +119,7 @@ bin_echoti(char *name, char **argv, UNUSED(Options ops), UNUSED(int func)) /* get the arguments */ for (arg=0; argv[arg]; arg++) { if (strarg && arg > 0) - pars[arg] = (long) argv[arg]; + pars[arg] = (long) unmetafy(dupstring(argv[arg]), NULL); else pars[arg] = atoi(argv[arg]); } @@ -134,8 +142,9 @@ static struct builtin bintab[] = { static HashNode getterminfo(UNUSED(HashTable ht), const char *name) { - int len, num; - char *tistr, *nameu; + int num; + char *tistr; + const char *t; Param pm = NULL; /* This depends on the termcap stuff in init.c */ @@ -144,22 +153,26 @@ getterminfo(UNUSED(HashTable ht), const char *name) if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term())) return NULL; - nameu = dupstring(name); - unmetafy(nameu, &len); + for (t = name; *t; t++) { + /* ncurses helpfully just crashes if you pass it nonascii */ + if ((unsigned char)*t > 0x7f) { + return NULL; + } + } pm = (Param) hcalloc(sizeof(struct param)); - pm->node.nam = nameu; + pm->node.nam = dupstring(name); pm->node.flags = PM_READONLY; - if (((num = tigetnum(nameu)) != -1) && (num != -2)) { + if (((num = tigetnum(name)) != -1) && (num != -2)) { pm->u.val = num; pm->node.flags |= PM_INTEGER; pm->gsu.i = &nullsetinteger_gsu; - } else if ((num = tigetflag(nameu)) != -1) { + } else if ((num = tigetflag(name)) != -1) { pm->u.str = num ? dupstring("yes") : dupstring("no"); pm->node.flags |= PM_SCALAR; pm->gsu.s = &nullsetscalar_gsu; - } else if ((tistr = (char *)tigetstr(nameu)) != NULL && tistr != (char *)-1) { + } else if ((tistr = (char *)tigetstr(name)) != NULL && tistr != (char *)-1) { pm->u.str = metafy(tistr, -1, META_HEAPDUP); pm->node.flags |= PM_SCALAR; pm->gsu.s = &nullsetscalar_gsu; |
