diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-21 16:30:44 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-02-21 16:30:44 +0100 |
commit | 45dd87aac05ddf8bbfb110fde85ef875f3adfb65 (patch) | |
tree | 2d18a0cc2abd0e15f4163f5dc1ce928739b8097d | |
parent | da2e46dff6576c29fa1d379c943bb7943aa6e7ce (diff) | |
download | busybox-w32-45dd87aac05ddf8bbfb110fde85ef875f3adfb65.tar.gz busybox-w32-45dd87aac05ddf8bbfb110fde85ef875f3adfb65.tar.bz2 busybox-w32-45dd87aac05ddf8bbfb110fde85ef875f3adfb65.zip |
ash: expand: Ensure result is escaped in cvtnum
Upstream commit:
Date: Fri, 1 Jun 2018 18:25:29 +0800
expand: Ensure result is escaped in cvtnum
The minus sign generated from arithmetic expansion is currently
unquoted which causes anomalies when the result is used in where
the quoting matters.
This patch fixes it by explicitly calling memtodest on the result
in cvtnum.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 49 | ||||
-rw-r--r-- | shell/ash_test/ash-quoting/negative_arith.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-quoting/negative_arith.tests | 8 | ||||
-rw-r--r-- | shell/hush_test/hush-quoting/negative_arith.right | 2 | ||||
-rwxr-xr-x | shell/hush_test/hush-quoting/negative_arith.tests | 8 |
5 files changed, 44 insertions, 25 deletions
diff --git a/shell/ash.c b/shell/ash.c index 8d1822847..005d87ecf 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6071,26 +6071,6 @@ static struct ifsregion *ifslastp; | |||
6071 | static struct arglist exparg; | 6071 | static struct arglist exparg; |
6072 | 6072 | ||
6073 | /* | 6073 | /* |
6074 | * Our own itoa(). | ||
6075 | * cvtnum() is used even if math support is off (to prepare $? values and such). | ||
6076 | */ | ||
6077 | static int | ||
6078 | cvtnum(arith_t num) | ||
6079 | { | ||
6080 | int len; | ||
6081 | |||
6082 | /* 32-bit and wider ints require buffer size of bytes*3 (or less) */ | ||
6083 | len = sizeof(arith_t) * 3; | ||
6084 | /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */ | ||
6085 | if (sizeof(arith_t) < 4) len += 2; | ||
6086 | |||
6087 | expdest = makestrspace(len, expdest); | ||
6088 | len = fmtstr(expdest, len, ARITH_FMT, num); | ||
6089 | STADJUST(len, expdest); | ||
6090 | return len; | ||
6091 | } | ||
6092 | |||
6093 | /* | ||
6094 | * Break the argument string into pieces based upon IFS and add the | 6074 | * Break the argument string into pieces based upon IFS and add the |
6095 | * strings to the argument list. The regions of the string to be | 6075 | * strings to the argument list. The regions of the string to be |
6096 | * searched for IFS characters have been stored by recordregion. | 6076 | * searched for IFS characters have been stored by recordregion. |
@@ -6347,16 +6327,18 @@ preglob(const char *pattern, int flag) | |||
6347 | /* | 6327 | /* |
6348 | * Put a string on the stack. | 6328 | * Put a string on the stack. |
6349 | */ | 6329 | */ |
6350 | static void | 6330 | static size_t |
6351 | memtodest(const char *p, size_t len, int flags) | 6331 | memtodest(const char *p, size_t len, int flags) |
6352 | { | 6332 | { |
6353 | int syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX; | 6333 | int syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX; |
6354 | char *q; | 6334 | char *q; |
6335 | char *s; | ||
6355 | 6336 | ||
6356 | if (!len) | 6337 | if (!len) |
6357 | return; | 6338 | return 0; |
6358 | 6339 | ||
6359 | q = makestrspace(len * 2, expdest); | 6340 | q = makestrspace(len * 2, expdest); |
6341 | s = q; | ||
6360 | 6342 | ||
6361 | do { | 6343 | do { |
6362 | unsigned char c = *p++; | 6344 | unsigned char c = *p++; |
@@ -6375,6 +6357,7 @@ memtodest(const char *p, size_t len, int flags) | |||
6375 | } while (--len); | 6357 | } while (--len); |
6376 | 6358 | ||
6377 | expdest = q; | 6359 | expdest = q; |
6360 | return q - s; | ||
6378 | } | 6361 | } |
6379 | 6362 | ||
6380 | static size_t | 6363 | static size_t |
@@ -6386,6 +6369,22 @@ strtodest(const char *p, int flags) | |||
6386 | } | 6369 | } |
6387 | 6370 | ||
6388 | /* | 6371 | /* |
6372 | * Our own itoa(). | ||
6373 | * cvtnum() is used even if math support is off (to prepare $? values and such). | ||
6374 | */ | ||
6375 | static int | ||
6376 | cvtnum(arith_t num, int flags) | ||
6377 | { | ||
6378 | /* 32-bit and wider ints require buffer size of bytes*3 (or less) */ | ||
6379 | /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */ | ||
6380 | int len = (sizeof(arith_t) >= 4) ? sizeof(arith_t) * 3 : sizeof(arith_t) * 3 + 2; | ||
6381 | char buf[len]; | ||
6382 | |||
6383 | len = fmtstr(buf, len, ARITH_FMT, num); | ||
6384 | return memtodest(buf, len, flags); | ||
6385 | } | ||
6386 | |||
6387 | /* | ||
6389 | * Record the fact that we have to scan this region of the | 6388 | * Record the fact that we have to scan this region of the |
6390 | * string for IFS characters. | 6389 | * string for IFS characters. |
6391 | */ | 6390 | */ |
@@ -6683,7 +6682,7 @@ expari(int flag) | |||
6683 | if (flag & QUOTES_ESC) | 6682 | if (flag & QUOTES_ESC) |
6684 | rmescapes(p + 1, 0, NULL); | 6683 | rmescapes(p + 1, 0, NULL); |
6685 | 6684 | ||
6686 | len = cvtnum(ash_arith(p + 1)); | 6685 | len = cvtnum(ash_arith(p + 1), flag); |
6687 | 6686 | ||
6688 | if (!(flag & EXP_QUOTED)) | 6687 | if (!(flag & EXP_QUOTED)) |
6689 | recordregion(begoff, begoff + len, 0); | 6688 | recordregion(begoff, begoff + len, 0); |
@@ -7328,7 +7327,7 @@ varvalue(char *name, int varflags, int flags, int quoted) | |||
7328 | if (num == 0) | 7327 | if (num == 0) |
7329 | return -1; | 7328 | return -1; |
7330 | numvar: | 7329 | numvar: |
7331 | len = cvtnum(num); | 7330 | len = cvtnum(num, flags); |
7332 | goto check_1char_name; | 7331 | goto check_1char_name; |
7333 | case '-': | 7332 | case '-': |
7334 | expdest = makestrspace(NOPTS, expdest); | 7333 | expdest = makestrspace(NOPTS, expdest); |
@@ -7494,7 +7493,7 @@ evalvar(char *p, int flag) | |||
7494 | varunset(p, var, 0, 0); | 7493 | varunset(p, var, 0, 0); |
7495 | 7494 | ||
7496 | if (subtype == VSLENGTH) { | 7495 | if (subtype == VSLENGTH) { |
7497 | cvtnum(varlen > 0 ? varlen : 0); | 7496 | cvtnum(varlen > 0 ? varlen : 0, flag); |
7498 | goto record; | 7497 | goto record; |
7499 | } | 7498 | } |
7500 | 7499 | ||
diff --git a/shell/ash_test/ash-quoting/negative_arith.right b/shell/ash_test/ash-quoting/negative_arith.right new file mode 100644 index 000000000..e7e51eee7 --- /dev/null +++ b/shell/ash_test/ash-quoting/negative_arith.right | |||
@@ -0,0 +1,2 @@ | |||
1 | tempfile0.tmp tempfile9.tmp | ||
2 | tempfile0.tmp tempfile1.tmp tempfile9.tmp | ||
diff --git a/shell/ash_test/ash-quoting/negative_arith.tests b/shell/ash_test/ash-quoting/negative_arith.tests new file mode 100755 index 000000000..8e47ca111 --- /dev/null +++ b/shell/ash_test/ash-quoting/negative_arith.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | >tempfile0.tmp | ||
2 | >tempfile1.tmp | ||
3 | >tempfile9.tmp | ||
4 | # The [...] is interpreted as: "any of the chars 0, -, and 9" | ||
5 | echo tempfile[0"$((-9))"].tmp | ||
6 | # The [...] is [0-9], interpreted as: "any digit" | ||
7 | echo tempfile[0$((-9))].tmp | ||
8 | rm tempfile?.tmp | ||
diff --git a/shell/hush_test/hush-quoting/negative_arith.right b/shell/hush_test/hush-quoting/negative_arith.right new file mode 100644 index 000000000..e7e51eee7 --- /dev/null +++ b/shell/hush_test/hush-quoting/negative_arith.right | |||
@@ -0,0 +1,2 @@ | |||
1 | tempfile0.tmp tempfile9.tmp | ||
2 | tempfile0.tmp tempfile1.tmp tempfile9.tmp | ||
diff --git a/shell/hush_test/hush-quoting/negative_arith.tests b/shell/hush_test/hush-quoting/negative_arith.tests new file mode 100755 index 000000000..8e47ca111 --- /dev/null +++ b/shell/hush_test/hush-quoting/negative_arith.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | >tempfile0.tmp | ||
2 | >tempfile1.tmp | ||
3 | >tempfile9.tmp | ||
4 | # The [...] is interpreted as: "any of the chars 0, -, and 9" | ||
5 | echo tempfile[0"$((-9))"].tmp | ||
6 | # The [...] is [0-9], interpreted as: "any digit" | ||
7 | echo tempfile[0$((-9))].tmp | ||
8 | rm tempfile?.tmp | ||