aboutsummaryrefslogtreecommitdiff
path: root/shell/math.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/math.c')
-rw-r--r--shell/math.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/shell/math.c b/shell/math.c
index eaf4f2453..aac5017d0 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -537,11 +537,40 @@ static arith_t strto_arith_t(const char *nptr, char **endptr)
537 base = (unsigned)n; 537 base = (unsigned)n;
538 n = 0; 538 n = 0;
539 nptr = *endptr + 1; 539 nptr = *endptr + 1;
540 /* bash allows "N#" (empty "nnnn" part) */ 540 for (;;) {
541 while (isdigit(*nptr)) { 541 unsigned digit = (unsigned)*nptr - '0';
542 if (digit >= 10 /* not 0..9 */
543 && digit <= 'z' - '0' /* needed to reject e.g. $((64#~)) */
544 ) {
545 /* in bases up to 36, case does not matter for a-z */
546 digit = (unsigned)(*nptr | 0x20) - ('a' - 10);
547 if (base > 36 && *nptr <= '_') {
548 /* otherwise, A-Z,@,_ are 36-61,62,63 */
549 if (*nptr == '_')
550 digit = 63;
551 else if (*nptr == '@')
552 digit = 62;
553 else if (digit < 36) /* A-Z */
554 digit += 36 - 10;
555 else
556 break; /* error: one of [\]^ */
557 }
558 //bb_error_msg("ch:'%c'%d digit:%u", *nptr, *nptr, digit);
559 //if (digit < 10) - example where we need this?
560 // break;
561 }
562 if (digit >= base)
563 break;
542 /* bash does not check for overflows */ 564 /* bash does not check for overflows */
543 n = n * base + (*nptr++ - '0'); 565 n = n * base + digit;
566 nptr++;
544 } 567 }
568 /* Note: we do not set errno on bad chars, we just set a pointer
569 * to the first invalid char. For example, this allows
570 * "N#" (empty "nnnn" part): 64#+1 is a valid expression,
571 * it means 64# + 1, whereas 64#~... is not, since ~ is not a valid
572 * operator.
573 */
545 *endptr = (char*)nptr; 574 *endptr = (char*)nptr;
546 return n; 575 return n;
547} 576}