Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: 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.
---
 Src/Modules/termcap.c  | 39 ++++++++++++++++++++++++++-------------
 Src/Modules/terminfo.c | 33 +++++++++++++++++++++++----------
 2 files changed, 49 insertions(+), 23 deletions(-)

diff --git a/Src/Modules/termcap.c b/Src/Modules/termcap.c
index af4009a3ac..fade8f1513 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 f9ab64fb30..7ce162e815 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;
-- 
2.38.1





Messages sorted by: Reverse Date, Date, Thread, Author