The -m, -n and -r options are converted with atoi(), which does not detect any error: it returns zero for a string that is not a number at all, and its behaviour on overflow is undefined.
So "-m foo" is silently taken as zero rather than rejected, and "-m 99999999999999999999" is undefined. The -n and -r cases are partly covered by their existing checks for zero, but only because a garbage value happens to convert to zero; "-n 4x" is accepted as four. The -m value is also scaled by 1024 * 1024 with no check, so a large enough value wraps around and asks for a small amount of memory. Use rte_kvargs_to_uint() for the three options, which converts the whole string and checks it against a range. EAL already depends on kvargs, so no new dependency is introduced. Note that this now bounds -m so that the scaled value cannot overflow size_t, which on a 32-bit build limits it to just under 4G; previously such a value was accepted and wrapped. Signed-off-by: Stephen Hemminger <[email protected]> --- lib/eal/common/eal_common_options.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c index 42cdef632f..519307bdc3 100644 --- a/lib/eal/common/eal_common_options.c +++ b/lib/eal/common/eal_common_options.c @@ -9,6 +9,7 @@ #include <ctype.h> #include <limits.h> #include <errno.h> +#include <stdint.h> #include <getopt.h> #include <sys/queue.h> #ifndef RTE_EXEC_ENV_WINDOWS @@ -29,6 +30,7 @@ #include <rte_tailq.h> #include <rte_version.h> #include <rte_devargs.h> +#include <rte_kvargs.h> #include <rte_memcpy.h> #ifndef RTE_EXEC_ENV_WINDOWS #include <rte_telemetry.h> @@ -2210,23 +2212,34 @@ eal_parse_args(void) /* memory options */ if (args.memory_size != NULL) { - int_cfg->memory = atoi(args.memory_size); - int_cfg->memory *= 1024ULL; - int_cfg->memory *= 1024ULL; + uint64_t mem; + + /* value is in megabytes, and must not overflow when scaled */ + if (rte_kvargs_to_uint(args.memory_size, 0, + SIZE_MAX / (1024 * 1024), &mem) < 0) { + EAL_LOG(ERR, "invalid memory size parameter"); + return -1; + } + int_cfg->memory = (size_t)mem * 1024 * 1024; } if (args.memory_channels != NULL) { - int_cfg->force_nchannel = atoi(args.memory_channels); - if (int_cfg->force_nchannel == 0) { + uint64_t channels; + + if (rte_kvargs_to_uint(args.memory_channels, 1, UINT_MAX, + &channels) < 0) { EAL_LOG(ERR, "invalid memory channel parameter"); return -1; } + int_cfg->force_nchannel = channels; } if (args.memory_ranks != NULL) { - int_cfg->force_nrank = atoi(args.memory_ranks); - if (int_cfg->force_nrank == 0 || int_cfg->force_nrank > 16) { + uint64_t ranks; + + if (rte_kvargs_to_uint(args.memory_ranks, 1, 16, &ranks) < 0) { EAL_LOG(ERR, "invalid memory rank parameter"); return -1; } + int_cfg->force_nrank = ranks; } if (args.no_huge) { int_cfg->no_hugetlbfs = 1; -- 2.53.0

