aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-01-10 13:22:25 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2018-01-10 13:22:25 +0100
commitbaa41c785551ae0580526298aa6fadf4534fc8c0 (patch)
treefd23926ca1e7d7f2be2b2b4e2dd24fb32a7e8501
parent2c876774a90ddb7478937ead096937f64e6bd7ec (diff)
downloadbusybox-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.c38
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
5785static 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;