diff mbox series

[3/4] Enforce type check in sw-description

Message ID 20240425124620.51594-3-stefano.babic@swupdate.org
State Accepted
Headers show
Series [1/4] Parser: statify get_value_* | expand

Commit Message

Stefano Babic April 25, 2024, 12:46 p.m. UTC
Attributes in sw-description are strictly typed and SWUpdate expects to
get values for the defined type. With the exception of strings,
attributes are parsed using a generic get_field() function, that
retrieves the value in the format set into sw-description, that can
differ from the expected one.

Add a set of macros to be used and to replace the generic get_field,
that is GET_FIELD_<type>, like GET_FIELD_STRING that already exists, and
checks for type before retrieving the value.

Signed-off-by: Stefano Babic <stefano.babic@swupdate.org>
---
 core/parsing_library.c              |  6 +++---
 core/swupdate.c                     |  6 +++---
 corelib/downloader.c                |  6 +++---
 corelib/parsing_library_libconfig.c | 27 ++++++++++++++++++++++++---
 corelib/parsing_library_libjson.c   | 27 +++++++++++++++++++++++----
 corelib/server_utils.c              |  2 +-
 corelib/swupdate_settings.c         |  4 ++--
 include/parselib.h                  | 28 ++++++++++++++++++++++++----
 mongoose/mongoose_interface.c       |  6 +++---
 parser/parser.c                     | 25 +++++++++++++------------
 suricatta/server_general.c          |  2 +-
 suricatta/server_hawkbit.c          |  8 ++++----
 suricatta/suricatta.c               |  2 +-
 13 files changed, 105 insertions(+), 44 deletions(-)

--
2.34.1
diff mbox series

Patch

diff --git a/core/parsing_library.c b/core/parsing_library.c
index 360545e6..f852799e 100644
--- a/core/parsing_library.c
+++ b/core/parsing_library.c
@@ -134,13 +134,13 @@  bool is_field_numeric(parsertype p, void *e, const char *path)
 	return false;
 }

-void get_field(parsertype p, void *e, const char *path, void *dest)
+void get_field(parsertype p, void *e, const char *path, void *dest, field_type_t type)
 {
 	switch (p) {
 	case LIBCFG_PARSER:
-		return get_field_cfg((config_setting_t *)e, path, dest);
+		return get_field_cfg((config_setting_t *)e, path, dest, type);
 	case JSON_PARSER:
-		return get_field_json((json_object *)e, path, dest);
+		return get_field_json((json_object *)e, path, dest, type);
 	default:
 		(void)e;
 		(void)path;
diff --git a/core/swupdate.c b/core/swupdate.c
index a421e888..df1c6bc0 100644
--- a/core/swupdate.c
+++ b/core/swupdate.c
@@ -325,9 +325,9 @@  static int read_globals_settings(void *elem, void *data)
 			WARN("Default Namaspace for SWUpdate vars cannot be set, possible side-effects");
 	}

-	get_field(LIBCFG_PARSER, elem, "verbose", &sw->verbose);
-	get_field(LIBCFG_PARSER, elem, "loglevel", &sw->loglevel);
-	get_field(LIBCFG_PARSER, elem, "syslog", &sw->syslog_enabled);
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "verbose", &sw->verbose);
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "loglevel", &sw->loglevel);
+	GET_FIELD_BOOL(LIBCFG_PARSER, elem, "syslog", &sw->syslog_enabled);
 	GET_FIELD_STRING(LIBCFG_PARSER, elem,
 				"no-downgrading", sw->minimum_version);
 	tmp[0] = '\0';
diff --git a/corelib/downloader.c b/corelib/downloader.c
index 99ba2265..b71cf461 100644
--- a/corelib/downloader.c
+++ b/corelib/downloader.c
@@ -106,11 +106,11 @@  static int download_settings(void *elem, void  __attribute__ ((__unused__)) *dat
 		opt->auth = NULL;
 	}

-	get_field(LIBCFG_PARSER, elem, "retries",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "retries",
 		&opt->retries);
-	get_field(LIBCFG_PARSER, elem, "retrywait",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "retrywait",
 		&opt->retry_sleep);
-	get_field(LIBCFG_PARSER, elem, "timeout",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "timeout",
 		&opt->low_speed_timeout);

 	return 0;
diff --git a/corelib/parsing_library_libconfig.c b/corelib/parsing_library_libconfig.c
index ec1dbc3b..64350f6e 100644
--- a/corelib/parsing_library_libconfig.c
+++ b/corelib/parsing_library_libconfig.c
@@ -19,9 +19,30 @@ 
 #include "util.h"
 #include "parselib.h"

-static void get_value_libconfig(const config_setting_t *e, void *dest)
+static unsigned int map_field_type(field_type_t type)
+{
+	switch (type) {
+	case TYPE_INT:
+		return CONFIG_TYPE_INT;
+	case TYPE_INT64:
+		return CONFIG_TYPE_INT64;
+	case TYPE_STRING:
+		return CONFIG_TYPE_STRING;
+	case TYPE_BOOL:
+		return CONFIG_TYPE_BOOL;
+	case TYPE_FLOAT:
+		return CONFIG_TYPE_FLOAT;
+	default: /* not supported in SWUpdate */
+		return CONFIG_TYPE_NONE;
+	}
+}
+
+
+static void get_value_libconfig(const config_setting_t *e, void *dest, field_type_t expected_type)
 {
 	int type = config_setting_type(e);
+	if (type != map_field_type(expected_type))
+		return;
 	switch (type) {
 	case CONFIG_TYPE_INT:
 		*(int *)dest = config_setting_get_int(e);
@@ -91,7 +112,7 @@  bool is_field_numeric_cfg(config_setting_t *e, const char *path)
 	       type == CONFIG_TYPE_FLOAT;
 }

-void get_field_cfg(config_setting_t *e, const char *path, void *dest)
+void get_field_cfg(config_setting_t *e, const char *path, void *dest, field_type_t type)
 {
 	config_setting_t *elem;

@@ -103,7 +124,7 @@  void get_field_cfg(config_setting_t *e, const char *path, void *dest)
 	if (!elem)
 		return;

-	get_value_libconfig(elem, dest);
+	get_value_libconfig(elem, dest, type);
 }

 const char *get_field_string_libconfig(config_setting_t *e, const char *path)
diff --git a/corelib/parsing_library_libjson.c b/corelib/parsing_library_libjson.c
index 43b73805..10fefc8a 100644
--- a/corelib/parsing_library_libjson.c
+++ b/corelib/parsing_library_libjson.c
@@ -21,6 +21,23 @@ 

 #define MAX_URL_LENGTH 2048

+static json_type map_field_type(field_type_t type)
+{
+	switch (type) {
+	case TYPE_INT:
+	case TYPE_INT64:
+		return json_type_int;
+	case TYPE_STRING:
+		return json_type_string;
+	case TYPE_BOOL:
+		return json_type_boolean;
+	case TYPE_FLOAT:
+		return json_type_double;
+	default: /* not supported in SWUpdate */
+		return json_type_null;
+	}
+}
+
 json_object *find_json_recursive_node(json_object *root, const char **names)
 {
 	json_object *node = root;
@@ -102,10 +119,12 @@  const char *get_field_string_json(json_object *e, const char *path)
 	return NULL;
 }

-static void get_value_json(json_object *e, void *dest)
+static void get_value_json(json_object *e, void *dest, field_type_t expected_type)
 {
 	enum json_type type;
 	type = json_object_get_type(e);
+	if (type != map_field_type(expected_type))
+		return;
 	switch (type) {
 	case json_type_boolean:
 		*(unsigned int *)dest = json_object_get_boolean(e);
@@ -141,15 +160,15 @@  bool is_field_numeric_json(json_object *e, const char *path)
 	       type == json_type_double;
 }

-void get_field_json(json_object *e, const char *path, void *dest)
+void get_field_json(json_object *e, const char *path, void *dest, field_type_t type)
 {
 	json_object *fld = NULL;

 	if (path) {
 		if (json_object_object_get_ex(e, path, &fld))
-			get_value_json(fld, dest);
+			get_value_json(fld, dest, type);
 	} else {
-		get_value_json(e, dest);
+		get_value_json(e, dest, type);
 	}
 }

diff --git a/corelib/server_utils.c b/corelib/server_utils.c
index f74b90c2..2b3c64e3 100644
--- a/corelib/server_utils.c
+++ b/corelib/server_utils.c
@@ -20,7 +20,7 @@  int channel_settings(void *elem, void *data)
 	char tmp[128];
 	channel_data_t *chan = (channel_data_t *)data;

-	get_field(LIBCFG_PARSER, elem, "retry",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "retry",
 		&chan->retries);

 	GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "max-download-speed", tmp);
diff --git a/corelib/swupdate_settings.c b/corelib/swupdate_settings.c
index ee2aa050..28d89a14 100644
--- a/corelib/swupdate_settings.c
+++ b/corelib/swupdate_settings.c
@@ -95,8 +95,8 @@  static int get_run_as(void *elem, void *data)
 {
 	struct run_as *pid = (struct run_as *)data;

-	get_field(LIBCFG_PARSER, elem, "userid", &pid->userid);
-	get_field(LIBCFG_PARSER, elem, "groupid", &pid->groupid);
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "userid", &pid->userid);
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "groupid", &pid->groupid);

 	return 0;
 }
diff --git a/include/parselib.h b/include/parselib.h
index d8c17bde..d278cbc4 100644
--- a/include/parselib.h
+++ b/include/parselib.h
@@ -15,6 +15,14 @@  typedef enum {
 	JSON_PARSER
 } parsertype;

+typedef enum {
+	TYPE_INT,
+	TYPE_INT64,
+	TYPE_STRING,
+	TYPE_BOOL,
+	TYPE_FLOAT
+} field_type_t;
+
 typedef void (*iterate_callback)(const char *name, const char *value,
 				 void *data);

@@ -33,7 +41,7 @@  typedef void (*iterate_callback)(const char *name, const char *value,
 #endif

 bool is_field_numeric_cfg(config_setting_t *e, const char *path);
-void get_field_cfg(config_setting_t *e, const char *path, void *dest);
+void get_field_cfg(config_setting_t *e, const char *path, void *dest, field_type_t type);
 void *get_child_libconfig(void *e, const char *name);
 void iterate_field_libconfig(config_setting_t *e, iterate_callback cb,
 			     void *data);
@@ -49,7 +57,7 @@  void *get_node_libconfig(config_t *cfg, const char **nodes);
 #define get_field_string_libconfig(e, path)	(NULL)
 #define get_child_libconfig(e, name)		(NULL)
 #define iterate_field_libconfig(e, cb, data)	{ }
-#define get_field_cfg(e, path, dest)
+#define get_field_cfg(e, path, dest, type)
 #define find_root_libconfig(cfg, nodes, depth)		(NULL)
 #define get_node_libconfig(cfg, nodes)		(NULL)
 #define is_field_numeric_cfg(e, path)	(false)
@@ -59,7 +67,7 @@  void *get_node_libconfig(config_t *cfg, const char **nodes);

 bool is_field_numeric_json(json_object *e, const char *path);
 const char *get_field_string_json(json_object *e, const char *path);
-void get_field_json(json_object *e, const char *path, void *dest);
+void get_field_json(json_object *e, const char *path, void *dest, field_type_t type);
 void *get_child_json(json_object *e, const char *name);
 void iterate_field_json(json_object *e, iterate_callback cb, void *data);
 json_object *find_json_recursive_node(json_object *root, const char **names);
@@ -79,7 +87,7 @@  int get_array_length(parsertype p, void *root);
 void *get_elem_from_idx(parsertype p, void *node, int idx);
 void *get_child(parsertype p, void *node, const char *name);
 void iterate_field(parsertype p, void *e, iterate_callback cb, void *data);
-void get_field(parsertype p, void *e, const char *path, void *dest);
+void get_field(parsertype p, void *e, const char *path, void *dest, field_type_t type);
 int exist_field_string(parsertype p, void *e, const char *path);
 void get_hash_value(parsertype p, void *elem, unsigned char *hash);
 void check_field_string(const char *src, char *dst, const size_t max_len);
@@ -94,3 +102,15 @@  bool set_find_path(const char **nodes, const char *newpath, char **tmp);
 	d[0] = '\0'; \
 	GET_FIELD_STRING(p, e, name, d); \
 } while (0)
+
+#define GET_FIELD_BOOL(p, e, path, dest) \
+	get_field(p, e, path, dest, TYPE_BOOL)
+
+#define GET_FIELD_INT(p, e, path, dest) \
+	get_field(p, e, path, dest, TYPE_INT)
+
+#define GET_FIELD_INT64(p, e, path, dest) \
+	get_field(p, e, path, dest, TYPE_INT64)
+
+#define GET_FIELD_FLOAT(p, e, path, dest) \
+	get_field(p, e, path, dest, TYPE_FLOAT)
diff --git a/mongoose/mongoose_interface.c b/mongoose/mongoose_interface.c
index 06fb2b06..3fbe88e2 100644
--- a/mongoose/mongoose_interface.c
+++ b/mongoose/mongoose_interface.c
@@ -741,7 +741,7 @@  static int mongoose_settings(void *elem, void  __attribute__ ((__unused__)) *dat
 		opts->root = strdup(tmp);
 	}

-	get_field(LIBCFG_PARSER, elem, "enable_directory_listing",
+	GET_FIELD_BOOL(LIBCFG_PARSER, elem, "enable_directory_listing",
 		  &opts->listing);

 	GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "listening_ports", tmp);
@@ -768,9 +768,9 @@  static int mongoose_settings(void *elem, void  __attribute__ ((__unused__)) *dat
 	if (strlen(tmp)) {
 		opts->auth_domain = strdup(tmp);
 	}
-	get_field(LIBCFG_PARSER, elem, "run-postupdate", &run_postupdate);
+	GET_FIELD_BOOL(LIBCFG_PARSER, elem, "run-postupdate", &run_postupdate);

-	get_field(LIBCFG_PARSER, elem, "timeout", &watchdog_conn);
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "timeout", &watchdog_conn);

 	return 0;
 }
diff --git a/parser/parser.c b/parser/parser.c
index b24cc781..04d7b72c 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -195,7 +195,7 @@  static bool get_common_fields(parsertype p, void *cfg, struct swupdate_cfg *swcf
 	} else {
 		swcfg->bootloader_state_marker = true;
 		if((setting = find_node(p, cfg, "bootloader_state_marker", swcfg)) != NULL) {
-			get_field(p, setting, NULL, &swcfg->bootloader_state_marker);
+			GET_FIELD_BOOL(p, setting, NULL, &swcfg->bootloader_state_marker);
 			TRACE("Setting bootloader state marker: %s",
 			      swcfg->bootloader_state_marker == true ? "true" : "false");
 		}
@@ -206,7 +206,7 @@  static bool get_common_fields(parsertype p, void *cfg, struct swupdate_cfg *swcf
 	} else {
 		swcfg->bootloader_transaction_marker = true;
 		if((setting = find_node(p, cfg, "bootloader_transaction_marker", swcfg)) != NULL) {
-			get_field(p, setting, NULL, &swcfg->bootloader_transaction_marker);
+			GET_FIELD_BOOL(p, setting, NULL, &swcfg->bootloader_transaction_marker);
 			TRACE("Setting bootloader transaction marker: %s",
 			      swcfg->bootloader_transaction_marker == true ? "true" : "false");
 		}
@@ -217,7 +217,7 @@  static bool get_common_fields(parsertype p, void *cfg, struct swupdate_cfg *swcf
 	 */
 	swcfg->reboot_required = true;
 	if((setting = find_node(p, cfg, "reboot", swcfg)) != NULL) {
-		get_field(p, setting, NULL, &swcfg->reboot_required);
+		GET_FIELD_BOOL(p, setting, NULL, &swcfg->reboot_required);
 	}

 	TRACE("reboot_required %d", swcfg->reboot_required);
@@ -230,7 +230,6 @@  static bool get_common_fields(parsertype p, void *cfg, struct swupdate_cfg *swcf
 			TRACE("Output file set but not enabled with -o, ignored");
 		} else {
 			GET_FIELD_STRING(p, setting, NULL, swcfg->output);
-			get_field(p, setting, NULL, &swcfg->output);
 			TRACE("Incoming SWU stored : %s", swcfg->output);
 		}
 	}
@@ -428,7 +427,7 @@  static int parse_common_attributes(parsertype p, void *elem, struct img_type *im
 	 * multiplier suffixes are allowed
 	 */
 	if (is_field_numeric(p, elem, "offset")) {
-		get_field(p, elem, "offset", &offset);
+		GET_FIELD_INT64(p, elem, "offset", &offset);
 		image->seek = offset;
 	} else {
 		GET_FIELD_STRING(p, elem, "offset", seek_str);
@@ -450,13 +449,15 @@  static int parse_common_attributes(parsertype p, void *elem, struct img_type *im
 			return -1;
 		}
 	} else {
-		get_field(p, elem, "compressed", &image->compressed);
+		bool img_compressed = false;
+		GET_FIELD_BOOL(p, elem, "compressed", &img_compressed);
+		image->compressed = img_compressed ? COMPRESSED_TRUE : COMPRESSED_FALSE;
 	}
-	get_field(p, elem, "installed-directly", &image->install_directly);
-	get_field(p, elem, "preserve-attributes", &image->preserve_attributes);
-	get_field(p, elem, "install-if-different", &image->id.install_if_different);
-	get_field(p, elem, "install-if-higher", &image->id.install_if_higher);
-	get_field(p, elem, "encrypted", &image->is_encrypted);
+	GET_FIELD_BOOL(p, elem, "installed-directly", &image->install_directly);
+	GET_FIELD_BOOL(p, elem, "preserve-attributes", &image->preserve_attributes);
+	GET_FIELD_BOOL(p, elem, "install-if-different", &image->id.install_if_different);
+	GET_FIELD_BOOL(p, elem, "install-if-higher", &image->id.install_if_higher);
+	GET_FIELD_BOOL(p, elem, "encrypted", &image->is_encrypted);
 	GET_FIELD_STRING(p, elem, "ivt", image->ivt_ascii);

 	if (is_image_installed(&cfg->installed_sw_list, image)) {
@@ -521,7 +522,7 @@  static int _parse_partitions(parsertype p, void *cfg, void *setting, const char
 			return -1;
 		}

-		get_field(p, elem, "size", &partition->partsize);
+		GET_FIELD_INT64(p, elem, "size", &partition->partsize);

 		add_properties(p, elem, partition);

diff --git a/suricatta/server_general.c b/suricatta/server_general.c
index bbe7cf0f..5c51fda6 100644
--- a/suricatta/server_general.c
+++ b/suricatta/server_general.c
@@ -591,7 +591,7 @@  static int server_general_settings(void *elem, void  __attribute__ ((__unused__)
 		SETSTRING(server_general.logurl, tmp);
 	}

-	get_field(LIBCFG_PARSER, elem, "polldelay",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "polldelay",
 		&server_general.polling_interval);

 	channel_settings(elem, &channel_data_defaults);
diff --git a/suricatta/server_hawkbit.c b/suricatta/server_hawkbit.c
index 5199eefe..3c38ea61 100644
--- a/suricatta/server_hawkbit.c
+++ b/suricatta/server_hawkbit.c
@@ -1726,18 +1726,18 @@  static int server_hawkbit_settings(void *elem, void  __attribute__ ((__unused__)
 		mandatory_argument_count |= URL_BIT;
 	}

-	get_field(LIBCFG_PARSER, elem, "polldelay",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "polldelay",
 		&server_hawkbit.polling_interval);

-	get_field(LIBCFG_PARSER, elem, "initial-report-resend-period",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "initial-report-resend-period",
 		&server_hawkbit.initial_report_resend_period);

 	channel_settings(elem, &channel_data_defaults);

-	get_field(LIBCFG_PARSER, elem, "usetokentodwl",
+	GET_FIELD_BOOL(LIBCFG_PARSER, elem, "usetokentodwl",
 		&server_hawkbit.usetokentodwl);

-	get_field(LIBCFG_PARSER, elem, "connection-timeout",
+	GET_FIELD_INT(LIBCFG_PARSER, elem, "connection-timeout",
 		&channel_data_defaults.connection_timeout);

 	GET_FIELD_STRING_RESET(LIBCFG_PARSER, elem, "targettoken", tmp);
diff --git a/suricatta/suricatta.c b/suricatta/suricatta.c
index 9f454d59..20eb427f 100644
--- a/suricatta/suricatta.c
+++ b/suricatta/suricatta.c
@@ -167,7 +167,7 @@  static server_op_res_t suricatta_ipc(int fd)

 static int suricatta_settings(void *elem, void  __attribute__ ((__unused__)) *data)
 {
-	get_field(LIBCFG_PARSER, elem, "enable",
+	GET_FIELD_BOOL(LIBCFG_PARSER, elem, "enable",
 		&enable);

 	char cfg_server[128];