[PATCH ulogd2 6/8] ulogd: improve integer option parsing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxx>
---
 include/ulogd/conffile.h |  2 ++
 src/conffile.c           | 17 ++++++++++++++++-
 src/ulogd.c              | 10 ++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)

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 7b9fb0f..f412804 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 96f88db..96cea8a 100644
--- a/src/ulogd.c
+++ b/src/ulogd.c
@@ -302,6 +302,16 @@ int ulogd_parse_configfile(const char *section, struct config_keyset *ce)
 				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;
--
2.48.1






[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux