about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/options.yo4
-rw-r--r--Src/math.c34
-rw-r--r--Src/utils.c5
-rw-r--r--Test/C01arith.ztst12
5 files changed, 51 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 0bf106413..3b6365bcf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2007-02-10  Peter Stephenson  <p.w.stephenson@ntlworld.com>
+
+	23165: Src/math.c, Src/utils.c, Doc/Zsh/options.yo: don't
+	try to parse base indicators in octal and raise error for
+	bases above 36.
+
 2007-02-10  Felix Rosencrantz <f.rosencrantz@gmail.com>
 	* 23164: Src/builtin.c when PUSHD_SILENT is set, don't print anything
 	from popd/pushd.
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index e1f3fc509..b929366c4 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1101,6 +1101,10 @@ Interpret any integer constant beginning with a 0 as octal, per IEEE Std
 1003.2-1992 (ISO 9945-2:1993).  This is not enabled by default as it
 causes problems with parsing of, for example, date and time strings with
 leading zeroes.
+
+Sequences of digits indicating a numeric base such as the `tt(08)'
+component in `tt(08#77)' are always interpreted as decimal, regardless
+of leading zeroes.
 )
 pindex(TYPESET_SILENT)
 item(tt(TYPESET_SILENT))(
diff --git a/Src/math.c b/Src/math.c
index 809999f9c..66d57fd53 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -216,17 +216,33 @@ lexconstant(void)
 	    lastbase = 16;
 	    return NUM;
 	}
-	else if (isset(OCTALZEROES) &&
-		 (memchr(nptr, '.', strlen(nptr)) == NULL) &&
-		 idigit(*nptr)) {
-	    yyval.u.l = zstrtol(ptr, &ptr, 0);
-	    lastbase = 8;
-	    return NUM;
+	else if (isset(OCTALZEROES))
+	{
+	    char *ptr2;
+
+	    /*
+	     * Make sure this is a real octal constant;
+	     * it can't be a base indication (always decimal)
+	     * or a floating point number.
+	     */
+	    for (ptr2 = nptr; idigit(*ptr2); ptr2++)
+		;
+
+	    if (ptr2 > nptr && *ptr2 != '.' && *ptr2 != 'e' &&
+		*ptr2 != 'E' && *ptr2 != '#')
+	    {
+		yyval.u.l = zstrtol(ptr, &ptr, 0);
+		lastbase = 8;
+		return NUM;
+	    }
+	    nptr = ptr2;
 	}
     }
-
-    while (idigit(*nptr))
-	nptr++;
+    else
+    {
+	while (idigit(*nptr))
+	    nptr++;
+    }
 
     if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') {
 	/* it's a float */
diff --git a/Src/utils.c b/Src/utils.c
index 2ea8ba991..0e7a7d2bb 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1803,7 +1803,10 @@ zstrtol(const char *s, char **t, int base)
 	    base = 8;
     }
     inp = s;
-    if (base <= 10)
+    if (base > 36) {
+	zerr("invalid base: %d", base);
+	return (zlong)0;
+    } else if (base <= 10)
 	for (; *s >= '0' && *s < ('0' + base); s++) {
 	    if (trunc)
 		continue;
diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst
index 9867b5d9a..e4ddebc12 100644
--- a/Test/C01arith.ztst
+++ b/Test/C01arith.ztst
@@ -136,3 +136,15 @@
   print $(( 5, (3 + 7, 4) ))
 0:commas and parentheses, part 1
 >4
+
+  (setopt octalzeroes; print $(( 08#77 )))
+0:octalzeroes doesn't affect bases
+>63
+
+  print $(( 36#z ))
+0:bases up to 36 work
+>35
+
+  print $(( 37#z ))
+1:bases beyond 36 don't work
+?(eval):1: invalid base: 37