msgbuf: Add pldm_msgbuf_extract_uint*_to_size APIs

Add pldm_msgbuf_extract_uint8_to_size(),
pldm_msgbuf_extract_uint16_to_size() and
pldm_msgbuf_extract_uint32_to_size() APIs to msgbuf API list. These are
the extractors which extract uint8_t/uint16_t/uint32_t to the size_t
destination. We mostly use size_t as the type to hold object size, but
extracting data to a size_t variable has not been properly supported.
These new APIs can bypass this limitation.

Example:

Extract from buffer the length of a variable length data represented by
`variable_field` struct, which has a field of size_t to represent
length.

Change-Id: I89f2600602bacf39f1f915a3496231dcc63fd6aa
Signed-off-by: Chau Ly <chaul@amperecomputing.com>
diff --git a/src/msgbuf.h b/src/msgbuf.h
index d33d8e9..a0e1204 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -1309,6 +1309,99 @@
 	return pldm__msgbuf_insert_array_void(dst, len, utf16, len);
 }
 
+/**
+ * @brief pldm_msgbuf uint8_t extractor for a size_t
+ *
+ * @param[in,out] ctx - pldm_msgbuf context for extractor
+ * @param[out] dst - destination of extracted value
+ *
+ * @return 0 if buffer accesses were in-bounds,
+ * -EINVAL if dst pointer is invalid,
+ * -EOVERFLOW is the buffer was out of bound.
+ */
+#define pldm_msgbuf_extract_uint8_to_size(ctx, dst)                            \
+	pldm__msgbuf_extract_uint8_to_size(ctx, &(dst))
+LIBPLDM_CC_NONNULL
+LIBPLDM_CC_ALWAYS_INLINE int
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+pldm__msgbuf_extract_uint8_to_size(struct pldm_msgbuf *ctx, size_t *dst)
+{
+	uint8_t value;
+	int rc;
+
+	rc = pldm__msgbuf_extract_uint8(ctx, &value);
+	if (rc) {
+		return rc;
+	}
+
+	static_assert(SIZE_MAX >= UINT8_MAX, "Invalid promotion");
+
+	*dst = value;
+	return 0;
+}
+
+/**
+ * @brief pldm_msgbuf uint16_t extractor for a size_t
+ *
+ * @param[in,out] ctx - pldm_msgbuf context for extractor
+ * @param[out] dst - destination of extracted value
+ *
+ * @return 0 if buffer accesses were in-bounds,
+ * -EINVAL if dst pointer is invalid,
+ * -EOVERFLOW is the buffer was out of bound.
+ */
+#define pldm_msgbuf_extract_uint16_to_size(ctx, dst)                           \
+	pldm__msgbuf_extract_uint16_to_size(ctx, &(dst))
+LIBPLDM_CC_NONNULL
+LIBPLDM_CC_ALWAYS_INLINE int
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+pldm__msgbuf_extract_uint16_to_size(struct pldm_msgbuf *ctx, size_t *dst)
+{
+	uint16_t value;
+	int rc;
+
+	rc = pldm__msgbuf_extract_uint16(ctx, &value);
+	if (rc) {
+		return rc;
+	}
+
+	static_assert(SIZE_MAX >= UINT16_MAX, "Invalid promotion");
+
+	*dst = value;
+	return 0;
+}
+
+/**
+ * @brief pldm_msgbuf uint32_t extractor for a size_t
+ *
+ * @param[in,out] ctx - pldm_msgbuf context for extractor
+ * @param[out] dst - destination of extracted value
+ *
+ * @return 0 if buffer accesses were in-bounds,
+ * -EINVAL if dst pointer is invalid,
+ * -EOVERFLOW is the buffer was out of bound.
+ */
+#define pldm_msgbuf_extract_uint32_to_size(ctx, dst)                           \
+	pldm__msgbuf_extract_uint32_to_size(ctx, &(dst))
+LIBPLDM_CC_NONNULL
+LIBPLDM_CC_ALWAYS_INLINE int
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+pldm__msgbuf_extract_uint32_to_size(struct pldm_msgbuf *ctx, size_t *dst)
+{
+	uint32_t value;
+	int rc;
+
+	rc = pldm__msgbuf_extract_uint32(ctx, &value);
+	if (rc) {
+		return rc;
+	}
+
+	static_assert(SIZE_MAX >= UINT32_MAX, "Invalid promotion");
+
+	*dst = value;
+	return 0;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tests/msgbuf.cpp b/tests/msgbuf.cpp
index 14f5d73..0c2169e 100644
--- a/tests/msgbuf.cpp
+++ b/tests/msgbuf.cpp
@@ -1439,3 +1439,109 @@
     ASSERT_EQ(pldm_msgbuf_complete(dst), 0);
     ASSERT_EQ(pldm_msgbuf_complete(src), -EOVERFLOW);
 }
+
+TEST(msgbuf, extract_one_uint8_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint8_t buf[1] = {0xa5};
+
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, sizeof(buf), buf, sizeof(buf)), 0);
+    EXPECT_EQ(pldm_msgbuf_extract_uint8_to_size(ctx, val), 0);
+    EXPECT_EQ(val, 0xa5);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), 0);
+}
+
+TEST(msgbuf, extract_under_uint8_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint8_t buf[1] = {};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, 0, buf, 0), 0);
+    ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+    EXPECT_NE(pldm_msgbuf_extract_uint8_to_size(ctx, val), 0);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), -EOVERFLOW);
+}
+
+TEST(msgbuf, extract_over_uint8_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint8_t buf[1] = {};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, 0, buf, 0), 0);
+    EXPECT_NE(pldm_msgbuf_extract_uint8_to_size(ctx, val), 0);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), -EOVERFLOW);
+}
+
+TEST(msgbuf, extract_one_uint16_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint16_t buf[1] = {htole16(0x5aa5)};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, sizeof(buf), buf, sizeof(buf)), 0);
+    EXPECT_EQ(pldm_msgbuf_extract_uint16_to_size(ctx, val), 0);
+    EXPECT_EQ(val, 0x5aa5);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), 0);
+}
+
+TEST(msgbuf, extract_under_uint16_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint16_t buf[1] = {};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, 0, buf, 0), 0);
+    ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+    EXPECT_NE(pldm_msgbuf_extract_uint16_to_size(ctx, val), 0);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), -EOVERFLOW);
+}
+
+TEST(msgbuf, extract_over_uint16_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint16_t buf[1] = {};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, 0, buf, 0), 0);
+    EXPECT_NE(pldm_msgbuf_extract_uint16_to_size(ctx, val), 0);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), -EOVERFLOW);
+}
+
+TEST(msgbuf, extract_one_uint32_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint32_t buf[1] = {htole32(0x5a00ffa5)};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, sizeof(buf), buf, sizeof(buf)), 0);
+    EXPECT_EQ(pldm_msgbuf_extract_uint32_to_size(ctx, val), 0);
+    EXPECT_EQ(val, 0x5a00ffa5);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), 0);
+}
+
+TEST(msgbuf, extract_under_uint32_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint32_t buf[1] = {};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, 0, buf, 0), 0);
+    ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+    EXPECT_NE(pldm_msgbuf_extract_uint32_to_size(ctx, val), 0);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), -EOVERFLOW);
+}
+
+TEST(msgbuf, extract_over_uint32_to_size)
+{
+    PLDM_MSGBUF_DEFINE_P(ctx);
+    uint32_t buf[1] = {};
+    size_t val;
+
+    ASSERT_EQ(pldm_msgbuf_init_errno(ctx, 0, buf, 0), 0);
+    EXPECT_NE(pldm_msgbuf_extract_uint32_to_size(ctx, val), 0);
+    EXPECT_EQ(pldm_msgbuf_complete(ctx), -EOVERFLOW);
+}