summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorubba Smith <corubba@gmx.de>2025-03-12 15:55:16 +0100
committerFlorian Westphal <fw@strlen.de>2025-03-12 16:22:34 +0100
commita6229ae0bbeb8fcb7f9ee5d1dddaae98c0c71176 (patch)
tree970bc9a2610b3a9091e8d127fbee16d05bc526c5
parent0ac16e540283e2fa6c89292a416448c944bd3483 (diff)
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 <corubba@gmx.de> Signed-off-by: Florian Westphal <fw@strlen.de>
-rw-r--r--include/ulogd/conffile.h2
-rw-r--r--src/conffile.c17
-rw-r--r--src/ulogd.c10
3 files changed, 28 insertions, 1 deletions
diff --git a/include/ulogd/conffile.h b/include/ulogd/conffile.h
index 1f3d563..fb54dea 100644
--- a/include/ulogd/conffile.h
+++ b/include/ulogd/conffile.h
@@ -19,6 +19,8 @@ enum {
ERRUNKN, /* unknown config key */
ERRSECTION, /* section not found */
ERRTOOLONG, /* string too long */
+ ERRINTFORMAT, /* integer format is invalid */
+ ERRINTRANGE, /* integer value is out of range */
};
/* maximum line length of config file entries */
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 <limits.h>
#include <ulogd/ulogd.h>
#include <ulogd/common.h>
#include <ulogd/conffile.h>
@@ -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);
diff --git a/src/ulogd.c b/src/ulogd.c
index 7260aeb..c844767 100644
--- a/src/ulogd.c
+++ b/src/ulogd.c
@@ -293,6 +293,16 @@ int ulogd_parse_configfile(const char *section, struct config_keyset *ce)
else
ulogd_log(ULOGD_ERROR, "string value is too long\n");
break;
+ case -ERRINTFORMAT:
+ ulogd_log(ULOGD_ERROR,
+ "integer has invalid format for key \"%s\"\n",
+ config_errce->key);
+ break;
+ case -ERRINTRANGE:
+ ulogd_log(ULOGD_ERROR,
+ "integer is out of range for key \"%s\"\n",
+ config_errce->key);
+ break;
}
return ULOGD_IRET_ERR;