From 4fd8c3394ba016e4a6f331c1d02985bb08c4c594 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Thu, 1 Sep 2022 14:05:43 +0200
Subject: [PATCH] fix a bug if setting the non_ima_spill2 non_ima_cmp_par2 in
 the cmp_ent_write_cmp_pars() functions add max_used_bits registry version to
 the compression entity header catch overflows in the cmp_cal_size_of_data()
 function

---
 include/cmp_data_types.h |  5 ++-
 include/cmp_entity.h     |  4 ++-
 lib/cmp_data_types.c     | 29 ++++++++++++---
 lib/cmp_entity.c         | 77 +++++++++++++++++++++++++++++++++-------
 test/meson.build         |  1 +
 5 files changed, 94 insertions(+), 22 deletions(-)

diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 9c8a470..8878557 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -84,7 +84,7 @@
 
 /* struct holding the maximum length of the different data products types in bits */
 struct cmp_max_used_bits {
-	unsigned int version;
+	uint8_t version;
 	unsigned int s_exp_flags;
 	unsigned int s_fx;
 	unsigned int s_efx;
@@ -127,8 +127,7 @@ struct cmp_max_used_bits {
 void cmp_set_max_used_bits(const struct cmp_max_used_bits *set_max_used_bits);
 struct cmp_max_used_bits cmp_get_max_used_bits(void);
 
-/* for internal use only! */
-extern struct cmp_max_used_bits max_used_bits;
+uint8_t cmp_get_max_used_bits_version(void);
 
 
 /* Source data header structure for multi entry packet */
diff --git a/include/cmp_entity.h b/include/cmp_entity.h
index 0c9a606..c56cef5 100644
--- a/include/cmp_entity.h
+++ b/include/cmp_entity.h
@@ -116,7 +116,7 @@ struct cmp_entity {
 	uint8_t  model_value_used;		/* used Model Updating Weighing Value */
 	uint16_t model_id;			/* Model ID */
 	uint8_t  model_counter;			/* Model Counter */
-	uint8_t  spare;
+	uint8_t  max_used_bits_version;
 	uint16_t lossy_cmp_par_used;		/* used Lossy Compression Parameters */
 	union {	/* specific Compression Entity Header for the different Data Product Types */
 		struct imagette_header ima;
@@ -174,6 +174,7 @@ int cmp_ent_set_cmp_mode(struct cmp_entity *ent, uint32_t cmp_mode_used);
 int cmp_ent_set_model_value(struct cmp_entity *ent, uint32_t model_value_used);
 int cmp_ent_set_model_id(struct cmp_entity *ent, uint32_t model_id);
 int cmp_ent_set_model_counter(struct cmp_entity *ent, uint32_t model_counter);
+int cmp_ent_set_max_used_bits_version(struct cmp_entity *ent, uint8_t max_used_bits_version);
 int cmp_ent_set_lossy_cmp_par(struct cmp_entity *ent, uint32_t lossy_cmp_par_used);
 
 
@@ -235,6 +236,7 @@ uint8_t cmp_ent_get_model_value_used(struct cmp_entity *ent);
 
 uint16_t cmp_ent_get_model_id(struct cmp_entity *ent);
 uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent);
+uint8_t cmp_ent_get_max_used_bits_version(struct cmp_entity *ent);
 uint16_t cmp_ent_get_lossy_cmp_par(struct cmp_entity *ent);
 
 
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index 8dd5792..5a01f8b 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -20,6 +20,8 @@
 #include <cmp_data_types.h>
 #include <cmp_debug.h>
 #include <byteorder.h>
+#include <stdint.h>
+#include <stdio.h>
 
 
 /* the maximum length of the different data products types in bits */
@@ -88,6 +90,17 @@ struct cmp_max_used_bits cmp_get_max_used_bits(void)
 }
 
 
+/**
+ * @brief get the version record form the max used bits registry
+ *
+ * @returns version of the max used bits registry
+ */
+
+uint8_t cmp_get_max_used_bits_version(void) {
+	return max_used_bits.version;
+}
+
+
 /**
  * @brief calculate the size of a sample for the different compression data type
  *
@@ -106,6 +119,8 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 	case DATA_TYPE_IMAGETTE_ADAPTIVE:
 	case DATA_TYPE_SAT_IMAGETTE:
 	case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE:
+	case DATA_TYPE_F_CAM_IMAGETTE:
+	case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE:
 		sample_size = sizeof(uint16_t);
 		break;
 	case DATA_TYPE_OFFSET:
@@ -155,7 +170,7 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 		break;
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
 	default:
 		debug_print("Error: Compression data type is not supported.\n");
 		break;
@@ -178,16 +193,20 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 unsigned int cmp_cal_size_of_data(unsigned int samples, enum cmp_data_type data_type)
 {
 	unsigned int s = size_of_a_sample(data_type);
+	uint64_t x; /* use 64 bit to catch overflow */
 
 	if (!s)
 		return 0;
 
-	s *= samples;
+	x = (uint64_t)s*samples;
 
 	if (!rdcu_supported_data_type_is_used(data_type))
-		s += MULTI_ENTRY_HDR_SIZE;
+		x += MULTI_ENTRY_HDR_SIZE;
+
+	if (x > UINT32_MAX) /* catch overflow */
+		return 0;
 
-	return s;
+	return (unsigned int)x;
 }
 
 
@@ -510,7 +529,7 @@ int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
 	/* TODO: implement F_CAM conversion */
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
 	default:
 		debug_print("Error: Can not swap endianness for this compression data type.\n");
 		return -1;
diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index 0296894..6a5b040 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -97,7 +97,7 @@ uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode_flag)
 		case DATA_TYPE_F_CAM_BACKGROUND:
 			size = NON_IMAGETTE_HEADER_SIZE;
 			break;
-		case DATA_TYPE_UNKOWN:
+		case DATA_TYPE_UNKNOWN:
 			size = 0;
 			break;
 		}
@@ -442,6 +442,27 @@ int cmp_ent_set_model_counter(struct cmp_entity *ent, uint32_t model_counter)
 }
 
 
+/**
+ * @brief set version identifier for the max. used bits registry in the
+ *	compression entity header
+ *
+ * @param ent			pointer to a compression entity
+ * @param max_used_bits_version	the identifier for the max. used bits registry
+ *
+ * @returns 0 on success, otherwise error
+ */
+
+int cmp_ent_set_max_used_bits_version(struct cmp_entity *ent, uint8_t max_used_bits_version)
+{
+	if (!ent)
+		return -1;
+
+	ent->max_used_bits_version = max_used_bits_version;
+
+	return 0;
+}
+
+
 /**
  * @brief set the used lossy compression parameter in the compression entity
  *	header
@@ -1108,7 +1129,7 @@ uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent)
  * @param ent	pointer to a compression entity
  *
  * @returns the data_type NOT including the uncompressed data bit on success,
- *	DATA_TYPE_UNKOWN on error
+ *	DATA_TYPE_UNKNOWN on error
  */
 
 enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
@@ -1116,13 +1137,13 @@ enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent)
 	enum cmp_data_type data_type;
 
 	if (!ent)
-		return DATA_TYPE_UNKOWN;
+		return DATA_TYPE_UNKNOWN;
 
 	data_type = be16_to_cpu(ent->data_type);
 	data_type &= (1U << RAW_BIT_DATA_TYPE_POS)-1; /* remove uncompressed data flag */
 
 	if (!cmp_data_type_valid(data_type))
-		data_type = DATA_TYPE_UNKOWN;
+		data_type = DATA_TYPE_UNKNOWN;
 
 	return data_type;
 }
@@ -1214,6 +1235,25 @@ uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent)
 }
 
 
+/**
+ * @brief get the version identifier for the max. used bits registry from the
+ *	compression entity header
+ *
+ * @param ent	pointer to a compression entity
+ *
+ * @returns the version identifier for the max. used bits registry on success,
+ *	0 on error
+ */
+
+uint8_t cmp_ent_get_max_use_bits_version(struct cmp_entity *ent)
+{
+	if (!ent)
+		return 0;
+
+	return ent->max_used_bits_version;
+}
+
+
 /**
  * @brief get the used lossy compression parameter from the compression entity header
  *
@@ -1598,10 +1638,15 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 	if (!ent)
 		return NULL;
 
+	data_type = cmp_ent_get_data_type(ent);
+	if (!cmp_data_type_valid(data_type)) {
+		debug_print("Error: Compression data type not supported.\n");
+		return NULL;
+	}
+
 	if (cmp_ent_get_data_type_raw_bit(ent))
 		return (uint8_t *)ent + GENERIC_HEADER_SIZE;
 
-	data_type = cmp_ent_get_data_type(ent);
 
 	switch (data_type) {
 	case DATA_TYPE_IMAGETTE:
@@ -1630,7 +1675,8 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent)
 	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_F_CAM_BACKGROUND:
 		return ent->non_ima.cmp_data;
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
+	default:
 		return NULL;
 	}
 
@@ -1777,6 +1823,8 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 		return -1;
 	if (cmp_ent_set_model_value(ent, cfg->model_value))
 		return -1;
+	if (cmp_ent_set_max_used_bits_version(ent, cmp_get_max_used_bits_version()))
+		return -1;
 	if (cmp_ent_set_lossy_cmp_par(ent, cfg->round))
 		return -1;
 
@@ -1819,9 +1867,9 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 		if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_mean))
 			return -1;
 
-		if (cmp_ent_set_non_ima_spill2(ent, cfg->cmp_par_variance))
+		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_variance))
 			return -1;
-		if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->spill_variance))
+		if (cmp_ent_set_non_ima_spill2(ent, cfg->spill_variance))
 			return -1;
 
 		if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_pixels_error))
@@ -1892,7 +1940,7 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 		/* TODO: fix this*/
 			return -1;
 		break;
-	case DATA_TYPE_UNKOWN:
+	case DATA_TYPE_UNKNOWN:
 	default:
 		return -1;
 	}
@@ -2187,7 +2235,7 @@ int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg)
 		/* TODO: fix this*/
 			return -1;
 		break;
-	case DATA_TYPE_UNKOWN: /* fall through */
+	case DATA_TYPE_UNKNOWN: /* fall through */
 	default:
 		return -1;
 	}
@@ -2341,8 +2389,8 @@ void cmp_ent_print(struct cmp_entity *ent)
 static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 {
 	uint32_t version_id, cmp_ent_size, original_size, cmp_mode_used,
-		 model_value_used, model_id, model_counter, lossy_cmp_par_used,
-		 start_coarse_time, end_coarse_time;
+		 model_value_used, model_id, model_counter, max_used_bits_version,
+		 lossy_cmp_par_used, start_coarse_time, end_coarse_time;
 	uint16_t start_fine_time, end_fine_time;
 	enum cmp_data_type data_type;
 	int raw_bit;
@@ -2386,7 +2434,7 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 		+ ((end_fine_time - start_fine_time)/256./256.));
 
 	data_type = cmp_ent_get_data_type(ent);
-	if (data_type != DATA_TYPE_UNKOWN)
+	if (data_type != DATA_TYPE_UNKNOWN)
 		printf("Data Product Type: %d\n", data_type);
 	else
 		printf("Data Product Type: unknown!");
@@ -2406,6 +2454,9 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent)
 	model_counter = cmp_ent_get_model_counter(ent);
 	printf("Model Counter: %u\n", model_counter);
 
+	max_used_bits_version = cmp_ent_get_max_use_bits_version(ent);
+	printf("Maximum Used Bits Registry Version: %u\n", max_used_bits_version);
+
 	lossy_cmp_par_used = cmp_ent_get_lossy_cmp_par(ent);
 	printf("Used Lossy Compression Parameters: %u\n", lossy_cmp_par_used);
 }
diff --git a/test/meson.build b/test/meson.build
index 4743653..145cdb8 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -37,3 +37,4 @@ subdir('cmp_tool')
 unity_dep = dependency('unity', fallback : ['unity', 'unity_dep'])
 
 subdir('cmp_icu')
+subdir('cmp_data_types')
-- 
GitLab