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);
+}