From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19714 invoked from network); 13 Mar 2000 09:34:56 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 13 Mar 2000 09:34:56 -0000 Received: (qmail 10706 invoked by alias); 13 Mar 2000 09:34:49 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 10104 Received: (qmail 10694 invoked from network); 13 Mar 2000 09:34:48 -0000 Date: Mon, 13 Mar 2000 10:34:47 +0100 (MET) Message-Id: <200003130934.KAA16098@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk In-reply-to: Alexandre Duret-Lutz's message of 09 Mar 2000 21:10:19 +0100 Subject: Re: `foo=foo; (( foo ))' => infinite recursion 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@informatik.hu-berlin.de