mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-11 06:20:21 +00:00
utils: fix range checking for get_u32/get_u64 et all
Be more careful about overflow in strtoXX routines. Checks are based on documented interface on man pages. Based on suggestion from "Mr Dash Four". Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
This commit is contained in:
parent
ce93fffe82
commit
697ac63905
138
lib/utils.c
138
lib/utils.c
@ -12,6 +12,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <fcntl.h>
|
||||
@ -38,9 +39,28 @@ int get_integer(int *val, const char *arg, int base)
|
||||
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
|
||||
res = strtol(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
|
||||
|
||||
/* If there were no digits at all, strtol() stores
|
||||
* the original value of nptr in *endptr (and returns 0).
|
||||
* In particular, if *nptr is not '\0' but **endptr is '\0' on return,
|
||||
* the entire string is valid.
|
||||
*/
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
|
||||
/* If an underflow occurs, strtol() returns LONG_MIN.
|
||||
* If an overflow occurs, strtol() returns LONG_MAX.
|
||||
* In both cases, errno is set to ERANGE.
|
||||
*/
|
||||
if ((res == LONG_MAX || res == LONG_MIN) && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
/* Outside range of int */
|
||||
if (res < INT_MIN || res > INT_MAX)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -87,9 +107,21 @@ int get_unsigned(unsigned *val, const char *arg, int base)
|
||||
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
|
||||
res = strtoul(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
|
||||
|
||||
/* empty string or trailing non-digits */
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
|
||||
/* overflow */
|
||||
if (res == ULONG_MAX && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
/* out side range of unsigned */
|
||||
if (res > UINT_MAX)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -107,17 +139,32 @@ int get_time_rtt(unsigned *val, const char *arg, int *raw)
|
||||
unsigned long res;
|
||||
char *p;
|
||||
|
||||
if (strchr(arg,'.') != NULL) {
|
||||
t = strtod(arg,&p);
|
||||
if (strchr(arg, '.') != NULL) {
|
||||
t = strtod(arg, &p);
|
||||
if (t < 0.0)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
res = strtoul(arg, &p, 0);
|
||||
if (res > UINT_MAX)
|
||||
|
||||
/* extra non-digits */
|
||||
if (!p || p == arg || *p)
|
||||
return -1;
|
||||
|
||||
/* over/underflow */
|
||||
if ((t == HUGE_VALF || t == HUGE_VALL) && errno == ERANGE)
|
||||
return -1;
|
||||
} else {
|
||||
res = strtoul(arg, &p, 0);
|
||||
|
||||
/* empty string or trailing non-digits */
|
||||
if (!p || p == arg || *p)
|
||||
return -1;
|
||||
|
||||
/* overflow */
|
||||
if (res == ULONG_MAX && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
t = (double)res;
|
||||
}
|
||||
|
||||
if (p == arg)
|
||||
return -1;
|
||||
*raw = 1;
|
||||
@ -151,9 +198,21 @@ int get_u64(__u64 *val, const char *arg, int base)
|
||||
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
|
||||
res = strtoull(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res == 0xFFFFFFFFULL)
|
||||
return -1;
|
||||
|
||||
/* empty string or trailing non-digits */
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
|
||||
/* overflow */
|
||||
if (res == ULLONG_MAX && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
/* in case ULL is 128 bits */
|
||||
if (res > 0xFFFFFFFFFFFFFFFFULL)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -166,8 +225,19 @@ int get_u32(__u32 *val, const char *arg, int base)
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
res = strtoul(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
|
||||
|
||||
/* empty string or trailing non-digits */
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
|
||||
/* overflow */
|
||||
if (res == ULONG_MAX && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
/* in case UL > 32 bits */
|
||||
if (res > 0xFFFFFFFFUL)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -180,8 +250,18 @@ int get_u16(__u16 *val, const char *arg, int base)
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
res = strtoul(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
|
||||
|
||||
/* empty string or trailing non-digits */
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
|
||||
/* overflow */
|
||||
if (res == ULONG_MAX && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
if (res > 0xFFFFUL)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -193,9 +273,19 @@ int get_u8(__u8 *val, const char *arg, int base)
|
||||
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
|
||||
res = strtoul(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res > 0xFF)
|
||||
/* empty string or trailing non-digits */
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
|
||||
/* overflow */
|
||||
if (res == ULONG_MAX && errno == ERANGE)
|
||||
return -1;
|
||||
|
||||
if (res > 0xFFUL)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -210,10 +300,13 @@ int get_s32(__s32 *val, const char *arg, int base)
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
res = strtol(arg, &ptr, base);
|
||||
if (ptr == arg || *ptr ||
|
||||
((res == LONG_MIN || res == LONG_MAX) && errno == ERANGE) ||
|
||||
res > INT32_MAX || res < INT32_MIN)
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
if ((res == LONG_MIN || res == LONG_MAX) && errno == ERANGE)
|
||||
return -1;
|
||||
if (res > INT32_MAX || res < INT32_MIN)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -226,8 +319,13 @@ int get_s16(__s16 *val, const char *arg, int base)
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
res = strtol(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
if ((res == LONG_MIN || res == LONG_MAX) && errno == ERANGE)
|
||||
return -1;
|
||||
if (res > 0x7FFF || res < -0x8000)
|
||||
return -1;
|
||||
|
||||
*val = res;
|
||||
return 0;
|
||||
}
|
||||
@ -240,7 +338,11 @@ int get_s8(__s8 *val, const char *arg, int base)
|
||||
if (!arg || !*arg)
|
||||
return -1;
|
||||
res = strtol(arg, &ptr, base);
|
||||
if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
|
||||
if (!ptr || ptr == arg || *ptr)
|
||||
return -1;
|
||||
if ((res == LONG_MIN || res == LONG_MAX) && errno == ERANGE)
|
||||
return -1;
|
||||
if (res > 0x7F || res < -0x80)
|
||||
return -1;
|
||||
*val = res;
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user