diff options
Diffstat (limited to 'int_array.c')
-rw-r--r-- | int_array.c | 95 |
1 files changed, 58 insertions, 37 deletions
diff --git a/int_array.c b/int_array.c index a8de3d55..e7913dea 100644 --- a/int_array.c +++ b/int_array.c @@ -89,6 +89,25 @@ is_integer(NODE *symbol, NODE *subs) if (subs == Nnull_string || do_mpfr) return NULL; + /* + * Protect against MAYBE_NUM values where the string may not regenerate + * correctly. There could be white space and/or a non-decimal value. + * If stfmt is not STFMT_UNUSED, it means that the string value was + * generated using CONVFMT or OFMT, so there is no info there. + */ + if ((subs->flags & STRCUR) != 0 && subs->stfmt == STFMT_UNUSED) { + char *cp = subs->stptr; + + if ( subs->stlen == 0 + || cp[0] == '0' + || isspace((unsigned char) cp[0]) + || isspace((unsigned char) cp[subs->stlen - 1]) + || ( subs->stlen >= 2 + && (cp[0] == '-' || cp[0] == '+') + && cp[1] == '0')) + return NULL; + } + if ((subs->flags & NUMINT) != 0) return & success_node; @@ -107,49 +126,51 @@ is_integer(NODE *symbol, NODE *subs) * a[-3]=1; print "-3" in a -- true */ - if ((subs->flags & (STRING|STRCUR)) != 0) { - char *cp = subs->stptr, *cpend, *ptr; - char save; - size_t len = subs->stlen; - - if (len == 0 || (! isdigit((unsigned char) *cp) && *cp != '-')) - return NULL; - if (len > 1 && - ((*cp == '0') /* "00", "011" .. */ - || (*cp == '-' && *(cp + 1) == '0') /* "-0", "-011" .. */ - ) - ) - return NULL; - if (len == 1 && *cp != '-') { /* single digit */ - subs->numbr = (long) (*cp - '0'); - if ((subs->flags & MAYBE_NUM) != 0) { - subs->flags &= ~MAYBE_NUM; - subs->flags |= NUMBER; - } - subs->flags |= (NUMCUR|NUMINT); - return & success_node; - } + /* must be a STRING */ + char *cp = subs->stptr, *cpend, *ptr; + char save; + size_t len = subs->stlen; - cpend = cp + len; - save = *cpend; - *cpend = '\0'; + if (len == 0 || (! isdigit((unsigned char) *cp) && *cp != '-')) + return NULL; - errno = 0; - l = strtol(cp, & ptr, 10); - *cpend = save; - if (errno != 0 || ptr != cpend) - return NULL; - subs->numbr = l; + if (len > 1 && + ((*cp == '0') /* "00", "011" .. */ + || (*cp == '-' && *(cp + 1) == '0') /* "-0", "-011" .. */ + ) + ) + return NULL; + if (len == 1 && *cp != '-') { /* single digit */ + subs->numbr = (long) (*cp - '0'); if ((subs->flags & MAYBE_NUM) != 0) { - subs->flags &= ~MAYBE_NUM; + subs->flags &= ~(MAYBE_NUM|STRING); subs->flags |= NUMBER; } - subs->flags |= NUMCUR; - if (l <= INT32_MAX && l >= INT32_MIN) { - subs->flags |= NUMINT; - return & success_node; - } + subs->flags |= (NUMCUR|NUMINT); + return & success_node; + } + + cpend = cp + len; + save = *cpend; + *cpend = '\0'; + + errno = 0; + l = strtol(cp, & ptr, 10); + *cpend = save; + if (errno != 0 || ptr != cpend) + return NULL; + + subs->numbr = l; + if ((subs->flags & MAYBE_NUM) != 0) { + subs->flags &= ~(MAYBE_NUM|STRING); + subs->flags |= NUMBER; } + subs->flags |= NUMCUR; + if (l <= INT32_MAX && l >= INT32_MIN) { + subs->flags |= NUMINT; + return & success_node; + } + return NULL; } |