From 5fab157a593180525607b7d26263bee127f6be36 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 2 Nov 2021 10:43:27 +0100 Subject: [PATCH] topology: do not call strtol directly Introduce safe_strtol_base() function and redirects all strtol calls there. Also, improve error and value handling in callers. BugLink: https://github.com/alsa-project/alsa-lib/issues/187 Signed-off-by: Jaroslav Kysela --- src/topology/data.c | 6 +----- src/topology/ops.c | 13 ++++++++++--- src/topology/parser.c | 40 +++++++++++++++++++++++++++++----------- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/topology/data.c b/src/topology/data.c index 0546d63e..972b4b7a 100644 --- a/src/topology/data.c +++ b/src/topology/data.c @@ -414,12 +414,8 @@ static int write_hex(char *buf, char *str, int width) void *p = &val; errno = 0; - val = strtol(str, NULL, 16); - - if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) - || (errno != 0 && val == 0)) { + if (safe_strtol_base(str, &val, 16) < 0) return -EINVAL; - } switch (width) { case 1: diff --git a/src/topology/ops.c b/src/topology/ops.c index da175608..daab3577 100644 --- a/src/topology/ops.c +++ b/src/topology/ops.c @@ -34,15 +34,22 @@ static const struct map_elem control_map[] = { static int lookup_ops(const char *c) { - unsigned int i; + int i; + long ret; - for (i = 0; i < ARRAY_SIZE(control_map); i++) { + for (i = 0; i < (int)ARRAY_SIZE(control_map); i++) { if (strcmp(control_map[i].name, c) == 0) return control_map[i].id; } /* cant find string name in our table so we use its ID number */ - return strtol(c, NULL, 0); + i = safe_strtol(c, &ret); + if (i < 0) { + SNDERR("wrong kcontrol ops value string '%s'", c); + return i; + } + + return ret; } const char *tplg_ops_name(int type) diff --git a/src/topology/parser.c b/src/topology/parser.c index f34de01b..01c95afa 100644 --- a/src/topology/parser.c +++ b/src/topology/parser.c @@ -21,6 +21,25 @@ #include "list.h" #include "tplg_local.h" +/* + * Safe strtol call + */ +int safe_strtol_base(const char *str, long *val, int base) +{ + char *end; + long v; + if (!*str) + return -EINVAL; + errno = 0; + v = strtol(str, &end, base); + if (errno) + return -errno; + if (*end) + return -EINVAL; + *val = v; + return 0; +} + /* * Get integer value */ @@ -35,24 +54,23 @@ int tplg_get_integer(snd_config_t *n, int *val, int base) err = snd_config_get_integer(n, &lval); if (err < 0) return err; - if (lval < INT_MIN || lval > INT_MAX) - return -ERANGE; - *val = lval; - return err; + goto __retval; case SND_CONFIG_TYPE_STRING: err = snd_config_get_string(n, &str); if (err < 0) return err; - errno = 0; - *val = strtol(str, NULL, base); - if (errno == ERANGE) - return -ERANGE; - if (errno && *val == 0) - return -EINVAL; - return 0; + err = safe_strtol_base(str, &lval, base); + if (err < 0) + return err; + goto __retval; default: return -EINVAL; } + __retval: + if (lval < INT_MIN || lval > INT_MAX) + return -ERANGE; + *val = lval; + return 0; } /* -- 2.47.1