msgbuf: Add pldm_msgbuf_consumed()
pldm_msgbuf_consumed() only returns PLDM_SUCCESS if a message buffer has
been exactly exhausted - all bytes read and no overflow has occurred.
The decode_* functions have a mix of behaviour, some lenient like the
behaviour provided by pldm_msgbuf_validate() and others strict like
pldm_msgbuf_consumed().
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: If058ed3748dcc7cb366f4c31344c9bbfba1c5939
diff --git a/src/msgbuf.h b/src/msgbuf.h
index bf59388..662ba46 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -78,6 +78,26 @@
}
/**
+ * @brief Test whether a message buffer has been exactly consumed
+ *
+ * @param[in] ctx - pldm_msgbuf context for extractor
+ *
+ * @return PLDM_SUCCESS iff there are zero bytes of data that remain unread from
+ * the buffer and no overflow has occurred. Otherwise, PLDM_ERROR_INVALID_LENGTH
+ * indicates that an incorrect sequence of accesses have occurred, and
+ * PLDM_ERROR_INVALID_DATA indicates that the provided context was not a valid
+ * pointer.
+ */
+static inline int pldm_msgbuf_consumed(struct pldm_msgbuf *ctx)
+{
+ if (!ctx) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ return ctx->remaining == 0 ? PLDM_SUCCESS : PLDM_ERROR_INVALID_LENGTH;
+}
+
+/**
* @brief Destroy the pldm buf
*
* @param[in] ctx - pldm_msgbuf context for extractor
@@ -104,6 +124,33 @@
}
/**
+ * @brief Destroy the pldm_msgbuf instance, and check that the underlying buffer
+ * has been completely consumed without overflow
+ *
+ * @param[in] ctx - pldm_msgbuf context
+ *
+ * @return PLDM_SUCCESS if all buffer access were in-bounds and completely
+ * consume the underlying buffer. Otherwise, PLDM_ERROR_INVALID_DATA if the ctx
+ * parameter is invalid, or PLDM_ERROR_INVALID_LENGTH if prior accesses would
+ * have occurred byond the bounds of the buffer
+ */
+static inline int pldm_msgbuf_destroy_consumed(struct pldm_msgbuf *ctx)
+{
+ int consumed;
+
+ if (!ctx) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ consumed = pldm_msgbuf_consumed(ctx);
+
+ ctx->cursor = NULL;
+ ctx->remaining = 0;
+
+ return consumed;
+}
+
+/**
* @brief pldm_msgbuf extractor for a uint8_t
*
* @param[inout] ctx - pldm_msgbuf context for extractor
diff --git a/tests/msgbuf.cpp b/tests/msgbuf.cpp
index ad7fe25..1df195e 100644
--- a/tests/msgbuf.cpp
+++ b/tests/msgbuf.cpp
@@ -354,3 +354,38 @@
PLDM_SUCCESS);
ASSERT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+
+TEST(msgbuf, consumed_under)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+ uint8_t buf[1] = {};
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, sizeof(buf)), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy_consumed(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(msgbuf, consumed_exact)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+ uint8_t buf[1] = {};
+ uint8_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, sizeof(buf)), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_extract_uint8(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy_consumed(ctx), PLDM_SUCCESS);
+}
+
+TEST(msgbuf, consumed_over)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+ uint8_t buf[1] = {};
+ uint8_t val[2];
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, sizeof(buf)), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_extract_uint8(ctx, &val[0]), PLDM_SUCCESS);
+ EXPECT_NE(pldm_msgbuf_extract_uint8(ctx, &val[1]), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy_consumed(ctx), PLDM_ERROR_INVALID_LENGTH);
+}