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

Re: (LC_ALL=C; set -x 128 129; printf "%s\n" ${(#)@} | hexdump -C)



> 2023/09/01 2:38, I wrote:
> 
> So we need to reset (or save/restore) errflag somewhere...

The patch below is a simple save/restore errflag. It seems to work,
but I'm not sure it is the (or a) correct fix. I will not push this
unless I get positive responses.


By the way, the problem is not limited to the C locale. Even with
UTF-8 locale (tested on Linux. macOS may behave differently):

% a=( 0x8000_0000 0x8000_0001 )
% printf "%s\n" ${(#)a} | hexdump -C
00000000  22 0a 22                                          |"."|
00000003


Another problem (but I feel we don't need to fix it) is that
when we get error with the (X) flag seems to be rather arbitrary.
For positive values the lowest 4 bytes are used (subst.c:1503),
while for negative values only the lowest one byte is used
(subst.c:1511) and we never get warnings (tested on Fedora-38):

% printf "%s\n" ${(#X):-0x8000_0000}
zsh: character not in range
% printf "%s\n" ${(#X):-0x1_0000_0000} | hexdump -C
00000000  00 0a                                             |..|
00000002
% printf "%s\n" ${(#X):-0x1_8000_0000} | hexdump -C
zsh: character not in range
% printf "%s\n" ${(#X):--1} | hexdump -C
00000000  ff 0a                                             |..|
00000002
% printf "%s\n" ${(#X):--0x8000_0001} | hexdump -C
00000000  ff 0a                                             |..|
00000002



diff --git a/Src/subst.c b/Src/subst.c
index 14947ae36..6d9197d44 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3572,7 +3572,7 @@ colonsubscript:
     if (errflag)
 	return NULL;
     if (evalchar) {
-	int one = noerrs, oef = errflag, haserr = 0;
+	int one = noerrs, haserr = 0;
 
 	if (!quoteerr)
 	    noerrs = 1;
@@ -3582,28 +3582,33 @@ colonsubscript:
 	 */
 	if (isarr) {
 	    char **aval2, **avptr, **av2ptr;
+	    int tmp_errflag = 0; /* errflag==0 at this point */
 
 	    aval2 = (char **)zhalloc((arrlen(aval)+1)*sizeof(char *));
 
 	    for (avptr = aval, av2ptr = aval2; *avptr; avptr++, av2ptr++)
 	    {
-		/* When noerrs = 1, the only error is out-of-memory */
-		if (!(*av2ptr = substevalchar(*avptr))) {
+		/* errflag must be cleared when calling substevalchar().
+		 * It will set errflag if conversion fails. */
+		errflag = 0;
+		*av2ptr = substevalchar(*avptr);
+		tmp_errflag |= errflag;
+		if (!*av2ptr) { /* not a valid numerical expression? */
 		    haserr = 1;
 		    break;
 		}
 	    }
+	    errflag = tmp_errflag;
 	    *av2ptr = NULL;
 	    aval = aval2;
 	} else {
-	    /* When noerrs = 1, the only error is out-of-memory */
 	    if (!(val = substevalchar(val)))
 		haserr = 1;
 	}
 	noerrs = one;
 	if (!quoteerr) {
 	    /* Retain user interrupt error status */
-	    errflag = oef | (errflag & ERRFLAG_INT);
+	    errflag &= ERRFLAG_INT;
 	}
 	if (haserr || errflag)
 	    return NULL;






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