From a6229ae0bbeb8fcb7f9ee5d1dddaae98c0c71176 Mon Sep 17 00:00:00 2001 From: Corubba Smith Date: Wed, 12 Mar 2025 15:55:16 +0100 Subject: ulogd: improve integer option parsing The `value` union member in `struct config_entry` is declared as `int` since basically the beginning in e07722e46001 ("config stuff added"). The parsing was switched from the original `atoi()` in 015849995f7f ("Fix hexadecimal parsing in config file") to `strtoul()`. Switch the function for parsing to the signed `strtol()` variant since the result will be stored in a signed int, and it makes sense to support negative numbers. Detect when `strtol()` does not properly consume the whole argument and return a new format error. Also check the numerical value to make sure the signed int does not overflow, in which case a new range error is returned. Unfortunately there is no `strtoi()` which would do the proper range check itself, so the intermediate `long` and range-check for `int` is required. I also considered changing the `value` union member from `int` to `long`, which would make it possible to use the parsed value as-is. But since this is part of the api towards plugins (including third party) such a potentially breaking change felt unwarranted. This also means that still only 16bit integer values are *guaranteed* to work, although most platforms use bigger widths for int. Signed-off-by: Corubba Smith Signed-off-by: Florian Westphal --- src/conffile.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/conffile.c') diff --git a/src/conffile.c b/src/conffile.c index cc5552c..955956a 100644 --- a/src/conffile.c +++ b/src/conffile.c @@ -17,6 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -227,7 +228,21 @@ int config_parse_file(const char *section, struct config_keyset *kset) } break; case CONFIG_TYPE_INT: - ce->u.value = strtoul(args, NULL, 0); + errno = 0; + char *endptr = NULL; + long parsed = strtol(args, &endptr, 0); + if (endptr == args || *endptr != '\0') { + config_errce = ce; + err = -ERRINTFORMAT; + goto cpf_error; + } + if (errno == ERANGE || + parsed < INT_MIN || parsed > INT_MAX) { + config_errce = ce; + err = -ERRINTRANGE; + goto cpf_error; + } + ce->u.value = (int)parsed; break; case CONFIG_TYPE_CALLBACK: (ce->u.parser)(args); -- cgit v1.2.3