msgbuf: Add copy API
pldm_msgbuf_copy API allows copy of data from one msg buffer
to another. This was done earlier with a pldm_msgbuf_extract()
followed by pldm_msgbuf_insert().
Change-Id: I159792f726916761894aefb0a8795f1f0dc84114
Signed-off-by: Varsha Kaverappa <vkaverap@in.ibm.com>
diff --git a/src/msgbuf.h b/src/msgbuf.h
index f81eb13..1f71e4c 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -884,6 +884,62 @@
return PLDM_SUCCESS;
}
+
+/**
+ * @brief pldm_msgbuf copy data between two msg buffers
+ *
+ * @param[inout] src - pldm_msgbuf for source from where value should be copied
+ * @param[inout] dst - destination of copy from source
+ * @param[in] size - size of data to be copied
+ * @param[in] description - description of data copied
+ *
+ * @return PLDM_SUCCESS if buffer accesses were in-bounds,
+ * PLDM_ERROR_INVALID_LENGTH otherwise.
+ * PLDM_ERROR_INVALID_DATA if input is invalid
+ */
+#define pldm_msgbuf_copy(dst, src, type, name) \
+ pldm__msgbuf_copy(dst, src, sizeof(type), #name)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_copy(struct pldm_msgbuf *dst,
+ struct pldm_msgbuf *src, size_t size,
+ const char *description)
+{
+ if (!src || !src->cursor || !dst || !dst->cursor || !description) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+#if INTMAX_MAX < SIZE_MAX
+ if (size > INTMAX_MAX) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+#endif
+
+ if (src->remaining < INTMAX_MIN + (intmax_t)size) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ if (dst->remaining < INTMAX_MIN + (intmax_t)size) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ src->remaining -= (intmax_t)size;
+ assert(src->remaining >= 0);
+ if (src->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ dst->remaining -= (intmax_t)size;
+ assert(dst->remaining >= 0);
+ if (dst->remaining < 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ memcpy(dst->cursor, src->cursor, size);
+ src->cursor += size;
+ dst->cursor += size;
+
+ return PLDM_SUCCESS;
+}
#ifdef __cplusplus
}
#endif
diff --git a/tests/msgbuf.cpp b/tests/msgbuf.cpp
index fecf514..cfe7914 100644
--- a/tests/msgbuf.cpp
+++ b/tests/msgbuf.cpp
@@ -944,3 +944,56 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctxExtract), PLDM_SUCCESS);
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_SUCCESS);
}
+
+TEST(msgbuf, pldm_msgbuf_copy_good)
+{
+ struct pldm_msgbuf _src;
+ struct pldm_msgbuf* src = &_src;
+ uint16_t buf[1] = {htole16(0x5aa5)};
+
+ ASSERT_EQ(pldm_msgbuf_init(src, sizeof(buf), buf, sizeof(buf)),
+ PLDM_SUCCESS);
+
+ struct pldm_msgbuf _dst;
+ struct pldm_msgbuf* dst = &_dst;
+ uint16_t checkVal = 0;
+ uint8_t buf1[sizeof(buf)] = {};
+
+ ASSERT_EQ(pldm_msgbuf_init(dst, sizeof(buf1), buf1, sizeof(buf1)),
+ PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_copy(dst, src, buf[0], name), PLDM_SUCCESS);
+
+ ASSERT_EQ(pldm_msgbuf_init(dst, sizeof(buf1), buf1, sizeof(buf1)),
+ PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_extract_uint16(dst, &checkVal), PLDM_SUCCESS);
+
+ EXPECT_EQ(buf[0], checkVal);
+ EXPECT_EQ(pldm_msgbuf_destroy(src), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(dst), PLDM_SUCCESS);
+}
+
+TEST(msgbuf, pldm_msgbuf_copy_bad)
+{
+ struct pldm_msgbuf _src;
+ struct pldm_msgbuf* src = &_src;
+ struct pldm_msgbuf _dst;
+ struct pldm_msgbuf* dst = &_dst;
+ uint8_t buf[1] = {sizeof(uint8_t)};
+ uint8_t buf1[1] = {sizeof(uint16_t)};
+ uint16_t value = 8;
+
+ EXPECT_EQ(pldm_msgbuf_copy(dst, NULL, buf[0], name),
+ PLDM_ERROR_INVALID_DATA);
+ EXPECT_EQ(pldm_msgbuf_copy(NULL, src, buf[0], name),
+ PLDM_ERROR_INVALID_DATA);
+
+ ASSERT_EQ(pldm_msgbuf_init(src, 0, buf, sizeof(buf)), PLDM_SUCCESS);
+ ASSERT_EQ(pldm_msgbuf_init(dst, 0, buf1, sizeof(buf1)), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_copy(dst, src, value, name),
+ PLDM_ERROR_INVALID_LENGTH);
+
+ ASSERT_EQ(pldm_msgbuf_init(src, 0, buf1, sizeof(buf1)), PLDM_SUCCESS);
+ ASSERT_EQ(pldm_msgbuf_init(dst, 0, buf, sizeof(buf)), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_copy(dst, src, value, name),
+ PLDM_ERROR_INVALID_LENGTH);
+}