aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/gtlv/gtlv_dec_enc.h6
-rw-r--r--src/libosmo-gtlv/gtlv_dec_enc.c35
-rw-r--r--src/libosmo-gtlv/gtlv_gen.c3
-rw-r--r--tests/libosmo-gtlv/gtlv_dec_enc_test.c3
4 files changed, 33 insertions, 14 deletions
diff --git a/include/osmocom/gtlv/gtlv_dec_enc.h b/include/osmocom/gtlv/gtlv_dec_enc.h
index 132239f..cb62fe3 100644
--- a/include/osmocom/gtlv/gtlv_dec_enc.h
+++ b/include/osmocom/gtlv/gtlv_dec_enc.h
@@ -186,9 +186,9 @@ int osmo_gtlvs_decode(void *decoded_struct, unsigned int obj_ofs, struct osmo_gt
const struct osmo_gtlv_coding *ie_coding,
osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs);
-int osmo_gtlvs_encode(struct osmo_gtlv_put *gtlv, const void *decoded_struct, unsigned int obj_ofs,
- const struct osmo_gtlv_coding *ie_coding,
- osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs);
+int osmo_gtlvs_encode(struct osmo_gtlv_put *gtlv, const void *decoded_struct, size_t decoded_struct_size,
+ unsigned int obj_ofs, const struct osmo_gtlv_coding *ie_coding, osmo_gtlv_err_cb err_cb,
+ void *err_cb_data, const struct value_string *iei_strs);
int osmo_gtlvs_encode_to_str_buf(char *buf, size_t buflen, const void *decoded_struct, unsigned int obj_ofs,
const struct osmo_gtlv_coding *ie_coding, const struct value_string *iei_strs);
diff --git a/src/libosmo-gtlv/gtlv_dec_enc.c b/src/libosmo-gtlv/gtlv_dec_enc.c
index c3e45ea..be3002f 100644
--- a/src/libosmo-gtlv/gtlv_dec_enc.c
+++ b/src/libosmo-gtlv/gtlv_dec_enc.c
@@ -49,6 +49,19 @@
return RC; \
} while (0)
+/* Reverse offsetof(): return the address of the struct member for a given parent struct and member offset value.
+ * \param parent Pointer to the parent struct, e.g. decoded_struct as passed to osmo_gtlvs_decode().
+ * \param parent_size sizeof(*parent), for memory bounds checking, e.g. decoded_struct_size.
+ * \param memb_ofs byte offset to reach a member (e.g. osmo_gtlv_coding.memb_ofs, .presence_flag_ofs, ...). */
+static const void *membof_const(const void *parent, size_t parent_size, unsigned int memb_ofs)
+{
+ const uint8_t *p = parent;
+ const uint8_t *end = p + parent_size;
+ const uint8_t *memb = p + memb_ofs;
+ OSMO_ASSERT(memb < end);
+ OSMO_ASSERT(memb >= p);
+ return memb;
+}
/*! Decode a TLV structure from raw data to a decoded struct, for unordered TLV IEs.
* How to decode IE values and where to place them in the decoded struct, is defined by ie_coding, an array terminated
@@ -378,19 +391,22 @@ int osmo_gtlvs_decode(void *decoded_struct, unsigned int obj_ofs, struct osmo_gt
* \param[in] iei_strs value_string array to give IEI names in error messages passed to err_cb(), or NULL.
* \return 0 on success, negative on error.
*/
-int osmo_gtlvs_encode(struct osmo_gtlv_put *gtlv, const void *decoded_struct, unsigned int obj_ofs,
- const struct osmo_gtlv_coding *ie_coding,
- osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs)
+int osmo_gtlvs_encode(struct osmo_gtlv_put *gtlv, const void *decoded_struct, size_t decoded_struct_size,
+ unsigned int obj_ofs, const struct osmo_gtlv_coding *ie_coding, osmo_gtlv_err_cb err_cb,
+ void *err_cb_data, const struct value_string *iei_strs)
{
- void *obj = MEMB(decoded_struct, obj_ofs);
+ const void *obj = membof_const(decoded_struct, decoded_struct_size, obj_ofs);
+ size_t obj_maxlen = decoded_struct_size - obj_ofs;
if (!ie_coding)
return -ENOTSUP;
for (; !osmo_gtlv_coding_end(ie_coding); ie_coding++) {
int rc;
- bool *presence_flag_p = ie_coding->has_presence_flag ? MEMB(obj, ie_coding->presence_flag_ofs) : NULL;
- unsigned int *multi_count_p = ie_coding->has_count ? MEMB(obj, ie_coding->count_ofs) : NULL;
+ const bool *presence_flag_p = ie_coding->has_presence_flag ?
+ membof_const(obj, obj_maxlen, ie_coding->presence_flag_ofs) : NULL;
+ const unsigned int *multi_count_p = ie_coding->has_count ?
+ membof_const(obj, obj_maxlen, ie_coding->count_ofs) : NULL;
unsigned int n;
unsigned int i;
@@ -423,13 +439,14 @@ int osmo_gtlvs_encode(struct osmo_gtlv_put *gtlv, const void *decoded_struct, un
.cfg = ie_coding->nested_ies_cfg ? : gtlv->cfg,
.dst = gtlv->dst,
};
- rc = osmo_gtlvs_encode(&nested_tlv, decoded_struct, obj_ofs + memb_ofs,
- ie_coding->nested_ies, err_cb, err_cb_data, iei_strs);
+ rc = osmo_gtlvs_encode(&nested_tlv, decoded_struct, decoded_struct_size,
+ obj_ofs + memb_ofs, ie_coding->nested_ies,
+ err_cb, err_cb_data, iei_strs);
if (rc)
RETURN_ERROR(rc, ie_coding->ti,
"Error while encoding TLV structure nested inside this IE");
} else {
- rc = ie_coding->enc_func(gtlv, decoded_struct, MEMB(obj, memb_ofs));
+ rc = ie_coding->enc_func(gtlv, decoded_struct, membof_const(obj, obj_maxlen, memb_ofs));
if (rc)
RETURN_ERROR(rc, ie_coding->ti, "Error while encoding this IE");
}
diff --git a/src/libosmo-gtlv/gtlv_gen.c b/src/libosmo-gtlv/gtlv_gen.c
index fd3fbd9..9fe4b0c 100644
--- a/src/libosmo-gtlv/gtlv_gen.c
+++ b/src/libosmo-gtlv/gtlv_gen.c
@@ -388,7 +388,8 @@ static void write_c()
"int %s_ies_encode(struct osmo_gtlv_put *gtlv, const union %s_ies *src,\n"
" %s message_type, osmo_gtlv_err_cb err_cb, void *err_cb_data, const struct value_string *iei_strs)\n"
"{\n"
- " return osmo_gtlvs_encode(gtlv, src, 0, %s_get_msg_coding(message_type), err_cb, err_cb_data, iei_strs);\n"
+ " return osmo_gtlvs_encode(gtlv, src, sizeof(*src), 0, %s_get_msg_coding(message_type),\n"
+ " err_cb, err_cb_data, iei_strs);\n"
"}\n",
g_cfg->proto_name, g_cfg->proto_name, g_cfg->message_type_enum ? : "int", g_cfg->proto_name);
printf("\n"
diff --git a/tests/libosmo-gtlv/gtlv_dec_enc_test.c b/tests/libosmo-gtlv/gtlv_dec_enc_test.c
index e02a2e5..63de266 100644
--- a/tests/libosmo-gtlv/gtlv_dec_enc_test.c
+++ b/tests/libosmo-gtlv/gtlv_dec_enc_test.c
@@ -387,7 +387,8 @@ void test_enc_dec(const char *label, const struct osmo_gtlv_cfg *cfg, bool order
.cfg = cfg,
.dst = msgb_alloc(1024, __func__),
};
- rc = osmo_gtlvs_encode(&put, (void *)orig, 0, msg_ie_coding, err_cb, &verify_err_cb_data, tag_names);
+ rc = osmo_gtlvs_encode(&put, (void *)orig, sizeof(*orig), 0, msg_ie_coding,
+ err_cb, &verify_err_cb_data, tag_names);
printf("osmo_gtlvs_encode() rc = %d\n", rc);
printf("%s.\n", osmo_hexdump(put.dst->data, put.dst->len));