mirror of https://github.com/mirror/busybox.git
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>pull/7/head
parent
2c876774a9
commit
baa41c7855
38
shell/ash.c
38
shell/ash.c
|
@ -5780,6 +5780,26 @@ ash_arith(const char *s)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if BASH_SUBSTR
|
||||||
|
# if ENABLE_FEATURE_SH_MATH
|
||||||
|
static int substr_atoi(const char *s)
|
||||||
|
{
|
||||||
|
arith_t t = ash_arith(s);
|
||||||
|
if (sizeof(t) > sizeof(int)) {
|
||||||
|
/* clamp very large or very large negative nums for ${v:N:M}:
|
||||||
|
* else "${v:0:0x100000001}" would work as "${v:0:1}"
|
||||||
|
*/
|
||||||
|
if (t > INT_MAX)
|
||||||
|
t = INT_MAX;
|
||||||
|
if (t < INT_MIN)
|
||||||
|
t = INT_MIN;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# define substr_atoi(s) number(s)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* expandarg flags
|
* expandarg flags
|
||||||
|
@ -6816,13 +6836,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
|
||||||
|
|
||||||
loc = str = stackblock() + strloc;
|
loc = str = stackblock() + strloc;
|
||||||
|
|
||||||
# if !ENABLE_FEATURE_SH_MATH
|
|
||||||
# define ash_arith number
|
|
||||||
# endif
|
|
||||||
/* Read POS in ${var:POS:LEN} */
|
/* Read POS in ${var:POS:LEN} */
|
||||||
colon = strchr(loc, ':');
|
colon = strchr(loc, ':');
|
||||||
if (colon) *colon = '\0';
|
if (colon) *colon = '\0';
|
||||||
pos = ash_arith(loc);
|
pos = substr_atoi(loc);
|
||||||
if (colon) *colon = ':';
|
if (colon) *colon = ':';
|
||||||
|
|
||||||
/* Read LEN in ${var:POS:LEN} */
|
/* Read LEN in ${var:POS:LEN} */
|
||||||
|
@ -6830,7 +6847,6 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
|
||||||
/* *loc != '\0', guaranteed by parser */
|
/* *loc != '\0', guaranteed by parser */
|
||||||
if (quotes) {
|
if (quotes) {
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
/* Adjust the length by the number of escapes */
|
/* Adjust the length by the number of escapes */
|
||||||
for (ptr = startp; ptr < (str - 1); ptr++) {
|
for (ptr = startp; ptr < (str - 1); ptr++) {
|
||||||
if ((unsigned char)*ptr == CTLESC) {
|
if ((unsigned char)*ptr == CTLESC) {
|
||||||
|
@ -6842,19 +6858,15 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
|
||||||
orig_len = len;
|
orig_len = len;
|
||||||
if (*loc++ == ':') {
|
if (*loc++ == ':') {
|
||||||
/* ${var::LEN} */
|
/* ${var::LEN} */
|
||||||
len = ash_arith(loc);
|
len = substr_atoi(loc);
|
||||||
} else {
|
} else {
|
||||||
/* Skip POS in ${var:POS:LEN} */
|
/* Skip POS in ${var:POS:LEN} */
|
||||||
len = orig_len;
|
len = orig_len;
|
||||||
while (*loc && *loc != ':') {
|
while (*loc && *loc != ':')
|
||||||
loc++;
|
loc++;
|
||||||
|
if (*loc++ == ':')
|
||||||
|
len = substr_atoi(loc);
|
||||||
}
|
}
|
||||||
if (*loc++ == ':') {
|
|
||||||
len = ash_arith(loc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# undef ash_arith
|
|
||||||
|
|
||||||
if (pos < 0) {
|
if (pos < 0) {
|
||||||
/* ${VAR:$((-n)):l} starts n chars from the end */
|
/* ${VAR:$((-n)):l} starts n chars from the end */
|
||||||
pos = orig_len + pos;
|
pos = orig_len + pos;
|
||||||
|
|
Loading…
Reference in New Issue