Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: `foo=foo; (( foo ))' => infinite recursion
- X-seq: zsh-workers 10104
- From: Sven Wischnowsky <wischnow@xxxxxxxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxx
- Subject: Re: `foo=foo; (( foo ))' => infinite recursion
- Date: Mon, 13 Mar 2000 10:34:47 +0100 (MET)
- In-reply-to: Alexandre Duret-Lutz's message of 09 Mar 2000 21:10:19 +0100
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
Alexandre Duret-Lutz wrote:
> An easy way to die.
>
> ~ % zsh -f
> phobos% foo=foo; (( foo ))
> zsh: segmentation fault zsh -f
What really irritated me was that getnumvalue() called matheval().
That meant that in cases like the one above $foo could contain any
mathematical expression and that would get evaluated.
The patch makes it take only numbers from $foo (or integer-zero if
there is none). If that is considered to be the wrong idea we have to
find some other way to avoid the endless recusion, I think.
One question: currently it only skips white space at the beginning of
$foo to find the number (btw, all number-formats zsh knows of should
be understood); should we make it skip all non-numeric characters?
Bye
Sven
diff -ru ../z.old/Src/math.c Src/math.c
--- ../z.old/Src/math.c Mon Mar 13 10:18:27 2000
+++ Src/math.c Mon Mar 13 10:29:36 2000
@@ -950,6 +950,78 @@
return (x.type & MN_FLOAT) ? (zlong)x.u.d : x.u.l;
}
+/**/
+mod_export mnumber
+mathnumber(char *s)
+{
+ mnumber ret;
+
+ ret.type = MN_INTEGER;
+
+ while (*s) {
+ switch (*s++) {
+ case '[':
+ {
+ int base = zstrtol(s, &s, 10);
+
+ if (*s == ']')
+ s++;
+ ret.u.l = zstrtol(s, &s, base);
+ return ret;
+ }
+ case ' ':
+ case '\t':
+ case '\n':
+ break;
+ case '0':
+ if (*s == 'x' || *s == 'X') {
+ /* Should we set lastbase here? */
+ ret.u.l = zstrtol(++s, &s, 16);
+ return ret;
+ }
+ /* Fall through! */
+ default:
+ if (idigit(*--s) || *s == '.') {
+ char *nptr;
+#ifdef USE_LOCALE
+ char *prev_locale;
+#endif
+ for (nptr = s; idigit(*nptr); nptr++);
+
+ if (*nptr == '.' || *nptr == 'e' || *nptr == 'E') {
+ /* it's a float */
+ ret.type = MN_FLOAT;
+#ifdef USE_LOCALE
+ prev_locale = setlocale(LC_NUMERIC, NULL);
+ setlocale(LC_NUMERIC, "POSIX");
+#endif
+ ret.u.d = strtod(s, &nptr);
+#ifdef USE_LOCALE
+ setlocale(LC_NUMERIC, prev_locale);
+#endif
+ if (s == nptr || *nptr == '.')
+ goto end;
+ s = nptr;
+ } else {
+ /* it's an integer */
+ ret.u.l = zstrtol(s, &s, 10);
+
+ if (*s == '#')
+ ret.u.l = zstrtol(++s, &s, ret.u.l);
+ }
+ return ret;
+ }
+ goto end;
+ }
+ }
+ end:
+
+ ret.type = MN_INTEGER;
+ ret.u.l = 0;
+
+ return ret;
+}
+
/*
* Make sure we have an operator or an operand, whatever is expected.
* For this purpose, unary operators constitute part of an operand.
diff -ru ../z.old/Src/params.c Src/params.c
--- ../z.old/Src/params.c Mon Mar 13 10:18:27 2000
+++ Src/params.c Mon Mar 13 10:29:36 2000
@@ -1420,7 +1420,7 @@
mn.type = MN_FLOAT;
mn.u.d = v->pm->gets.ffn(v->pm);
} else
- return matheval(getstrvalue(v));
+ return mathnumber(getstrvalue(v));
return mn;
}
--
Sven Wischnowsky wischnow@xxxxxxxxxxxxxxxxxxxxxxx
Messages sorted by:
Reverse Date,
Date,
Thread,
Author