diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-01-10 13:22:25 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-01-10 13:22:25 +0100 |
commit | baa41c785551ae0580526298aa6fadf4534fc8c0 (patch) | |
tree | fd23926ca1e7d7f2be2b2b4e2dd24fb32a7e8501 | |
parent | 2c876774a90ddb7478937ead096937f64e6bd7ec (diff) | |
download | busybox-w32-baa41c785551ae0580526298aa6fadf4534fc8c0.tar.gz busybox-w32-baa41c785551ae0580526298aa6fadf4534fc8c0.tar.bz2 busybox-w32-baa41c785551ae0580526298aa6fadf4534fc8c0.zip |
ash: make ${v:N:M} more robust for very large M by clamping to MIN/MAX_INT
Before this patch, "${v:2:0x100000001}" = "${v:2:1}",
and similarly, constructs like "${v:2:9999999999}" may give wrong result
due to int overflows.
function old new delta
substr_atoi - 43 +43
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/shell/ash.c b/shell/ash.c index 83a8e77f9..a7f330c11 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -5780,6 +5780,26 @@ ash_arith(const char *s) | |||
5780 | return result; | 5780 | return result; |
5781 | } | 5781 | } |
5782 | #endif | 5782 | #endif |
5783 | #if BASH_SUBSTR | ||
5784 | # if ENABLE_FEATURE_SH_MATH | ||
5785 | static int substr_atoi(const char *s) | ||
5786 | { | ||
5787 | arith_t t = ash_arith(s); | ||
5788 | if (sizeof(t) > sizeof(int)) { | ||
5789 | /* clamp very large or very large negative nums for ${v:N:M}: | ||
5790 | * else "${v:0:0x100000001}" would work as "${v:0:1}" | ||
5791 | */ | ||
5792 | if (t > INT_MAX) | ||
5793 | t = INT_MAX; | ||
5794 | if (t < INT_MIN) | ||
5795 | t = INT_MIN; | ||
5796 | } | ||
5797 | return t; | ||
5798 | } | ||
5799 | # else | ||
5800 | # define substr_atoi(s) number(s) | ||
5801 | # endif | ||
5802 | #endif | ||
5783 | 5803 | ||
5784 | /* | 5804 | /* |
5785 | * expandarg flags | 5805 | * expandarg flags |
@@ -6816,13 +6836,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6816 | 6836 | ||
6817 | loc = str = stackblock() + strloc; | 6837 | loc = str = stackblock() + strloc; |
6818 | 6838 | ||
6819 | # if !ENABLE_FEATURE_SH_MATH | ||
6820 | # define ash_arith number | ||
6821 | # endif | ||
6822 | /* Read POS in ${var:POS:LEN} */ | 6839 | /* Read POS in ${var:POS:LEN} */ |
6823 | colon = strchr(loc, ':'); | 6840 | colon = strchr(loc, ':'); |
6824 | if (colon) *colon = '\0'; | 6841 | if (colon) *colon = '\0'; |
6825 | pos = ash_arith(loc); | 6842 | pos = substr_atoi(loc); |
6826 | if (colon) *colon = ':'; | 6843 | if (colon) *colon = ':'; |
6827 | 6844 | ||
6828 | /* Read LEN in ${var:POS:LEN} */ | 6845 | /* Read LEN in ${var:POS:LEN} */ |
@@ -6830,7 +6847,6 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6830 | /* *loc != '\0', guaranteed by parser */ | 6847 | /* *loc != '\0', guaranteed by parser */ |
6831 | if (quotes) { | 6848 | if (quotes) { |
6832 | char *ptr; | 6849 | char *ptr; |
6833 | |||
6834 | /* Adjust the length by the number of escapes */ | 6850 | /* Adjust the length by the number of escapes */ |
6835 | for (ptr = startp; ptr < (str - 1); ptr++) { | 6851 | for (ptr = startp; ptr < (str - 1); ptr++) { |
6836 | if ((unsigned char)*ptr == CTLESC) { | 6852 | if ((unsigned char)*ptr == CTLESC) { |
@@ -6842,19 +6858,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6842 | orig_len = len; | 6858 | orig_len = len; |
6843 | if (*loc++ == ':') { | 6859 | if (*loc++ == ':') { |
6844 | /* ${var::LEN} */ | 6860 | /* ${var::LEN} */ |
6845 | len = ash_arith(loc); | 6861 | len = substr_atoi(loc); |
6846 | } else { | 6862 | } else { |
6847 | /* Skip POS in ${var:POS:LEN} */ | 6863 | /* Skip POS in ${var:POS:LEN} */ |
6848 | len = orig_len; | 6864 | len = orig_len; |
6849 | while (*loc && *loc != ':') { | 6865 | while (*loc && *loc != ':') |
6850 | loc++; | 6866 | loc++; |
6851 | } | 6867 | if (*loc++ == ':') |
6852 | if (*loc++ == ':') { | 6868 | len = substr_atoi(loc); |
6853 | len = ash_arith(loc); | ||
6854 | } | ||
6855 | } | 6869 | } |
6856 | # undef ash_arith | ||
6857 | |||
6858 | if (pos < 0) { | 6870 | if (pos < 0) { |
6859 | /* ${VAR:$((-n)):l} starts n chars from the end */ | 6871 | /* ${VAR:$((-n)):l} starts n chars from the end */ |
6860 | pos = orig_len + pos; | 6872 | pos = orig_len + pos; |