fru: Introduce get_fru_record_by_option_check()
get_fru_record_by_option() protected the injection of record data into
the record buffer only using assert(). get_fru_record_by_option_check()
instead returns an error if the record data would overflow the record
buffer.
Callers should prefer get_fru_record_by_option_check(), and testing its
result, over get_fru_record_by_option().
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: Ifc1459863cd9f3f7289badb9f1842386d31cbd87
diff --git a/src/fru.c b/src/fru.c
index aeb7d50..39d8576 100644
--- a/src/fru.c
+++ b/src/fru.c
@@ -216,6 +216,17 @@
uint8_t *record_table, size_t *record_size,
uint16_t rsi, uint8_t rt, uint8_t ft)
{
+ int rc = get_fru_record_by_option_check(table, table_size, record_table,
+ record_size, rsi, rt, ft);
+ (void)rc;
+ assert(rc == PLDM_SUCCESS);
+}
+
+LIBPLDM_ABI_TESTING
+int get_fru_record_by_option_check(const uint8_t *table, size_t table_size,
+ uint8_t *record_table, size_t *record_size,
+ uint16_t rsi, uint8_t rt, uint8_t ft)
+{
const struct pldm_fru_record_data_format *record_data_src =
(const struct pldm_fru_record_data_format *)table;
struct pldm_fru_record_data_format *record_data_dest;
@@ -246,6 +257,9 @@
sizeof(struct pldm_fru_record_tlv);
assert(pos - record_table + len < *record_size);
+ if (pos - record_table + len >= *record_size) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
memcpy(pos, record_data_src, len);
record_data_dest = (struct pldm_fru_record_data_format *)pos;
@@ -257,6 +271,9 @@
len = sizeof(*tlv) - 1 + tlv->length;
if (tlv->type == ft || ft == 0) {
assert(pos - record_table + len < *record_size);
+ if (pos - record_table + len >= *record_size) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
memcpy(pos, tlv, len);
pos += len;
count++;
@@ -270,6 +287,8 @@
}
*record_size = pos - record_table;
+
+ return PLDM_SUCCESS;
}
LIBPLDM_ABI_STABLE