]> git.ipfire.org Git - thirdparty/ulogd2.git/commitdiff
ulogd: improve integer option parsing
authorCorubba Smith <corubba@gmx.de>
Wed, 12 Mar 2025 14:55:16 +0000 (15:55 +0100)
committerFlorian Westphal <fw@strlen.de>
Wed, 12 Mar 2025 15:22:34 +0000 (16:22 +0100)
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>
include/ulogd/conffile.h
src/conffile.c
src/ulogd.c

index 1f3d563fb3cd625add92247c4c5af4af1b9c80e8..fb54dea018c7246d8aa9f37058466b3553ee631c 100644 (file)
@@ -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 */
index cc5552c4731605d11ec429af9d0993ee1467a936..955956ab27426f3e0114c9d9751d0270cc7e154f 100644 (file)
@@ -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);
index 7260aebb1dbae96c9351fa334e7d079e4708c56f..c844767ad7b3f274ebdc349490bcb12626709fb0 100644 (file)
@@ -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;