summaryrefslogtreecommitdiffhomepage
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-09-22 23:40:10 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-09-22 23:40:10 +0200
commitc58d785b9d0a337ff884002c4cef5283f901c9e4 (patch)
tree7205c93cf29463ac9e1d7129ba08544124886373 /shell
parentca1ce4b9fa2b48f8898a51782543fe32546ba1ec (diff)
ash: fix BASE###nn bashism for bases 36..64
function old new delta evaluate_string 876 932 +56 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/math.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/shell/math.c b/shell/math.c
index 0c806ad39..af1ab55c0 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -540,11 +540,29 @@ static arith_t strto_arith_t(const char *nptr, char **endptr)
/* bash allows "N#" (empty "nnnn" part) */
for (;;) {
unsigned digit = (unsigned)*nptr - '0';
- if (digit >= 10 || digit >= base) {
+ if (digit >= 10) {
+ /* *nptr is not 0..9 */
+ if (*nptr > 'z')
+ break; /* this rejects e.g. $((64#~)) */
+ /* in bases up to 36, case does not matter for a-z */
digit = (unsigned)(*nptr | 0x20) - ('a' - 10);
- if (digit >= base)
- break;
+ if (base > 36 && *nptr <= '_') {
+ /* otherwise, A-Z,@,_ are 36..61,62,63 */
+ if (*nptr == '@')
+ digit = 62;
+ else if (*nptr == '_')
+ digit = 63;
+ else if (digit < 36) /* A-Z */
+ digit += 36 - 10;
+ else
+ break; /* error, such as [ or \ */
+ }
+ //bb_error_msg("ch:'%c'%d digit:%u", *nptr, *nptr, digit);
+ //if (digit < 10) - example where we need this?
+ // break;
}
+ if (digit >= base)
+ break;
/* bash does not check for overflows */
n = n * base + digit;
nptr++;