msgbuf: Add pldm_msgbuf_copy_string_utf16()
Safely copy a NUL-terminated UTF16-{BE,LE} string between msgbuf
instances.
Change-Id: If96df9598f17ac771d75f0831be270c5e0139578
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
diff --git a/src/msgbuf.h b/src/msgbuf.h
index 0936bac..1d06a75 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -1294,6 +1294,21 @@
return pldm__msgbuf_insert_array_void(dst, ascii, len);
}
+__attribute__((always_inline)) static inline int
+pldm_msgbuf_copy_string_utf16(struct pldm_msgbuf *dst, struct pldm_msgbuf *src)
+{
+ void *utf16 = NULL;
+ size_t len = 0;
+ int rc;
+
+ rc = pldm_msgbuf_span_string_utf16(src, &utf16, &len);
+ if (rc < 0) {
+ return rc;
+ }
+
+ return pldm__msgbuf_insert_array_void(dst, utf16, len);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/tests/msgbuf.cpp b/tests/msgbuf.cpp
index f2c9aca..c84acce 100644
--- a/tests/msgbuf.cpp
+++ b/tests/msgbuf.cpp
@@ -1434,3 +1434,77 @@
ASSERT_EQ(pldm_msgbuf_destroy(dst), 0);
ASSERT_EQ(pldm_msgbuf_destroy(src), -EOVERFLOW);
}
+
+TEST(msgbuf, pldm_msgbuf_copy_utf16_exact)
+{
+ const char16_t msg[] = u"this is a message";
+
+ struct pldm_msgbuf _src;
+ struct pldm_msgbuf* src = &_src;
+ struct pldm_msgbuf _dst;
+ struct pldm_msgbuf* dst = &_dst;
+
+ char buf[sizeof(msg)] = {};
+
+ ASSERT_EQ(pldm_msgbuf_init_errno(src, 0, msg, sizeof(msg)), 0);
+ ASSERT_EQ(pldm_msgbuf_init_errno(dst, 0, buf, sizeof(buf)), 0);
+ EXPECT_EQ(pldm_msgbuf_copy_string_utf16(dst, src), 0);
+ ASSERT_EQ(pldm_msgbuf_destroy(dst), 0);
+ ASSERT_EQ(pldm_msgbuf_destroy(src), 0);
+ EXPECT_EQ(0, memcmp(buf, msg, sizeof(msg)));
+}
+
+TEST(msgbuf, pldm_msgbuf_copy_utf16_dst_exceeds_src)
+{
+ const char16_t msg[] = u"this is a message";
+
+ struct pldm_msgbuf _src;
+ struct pldm_msgbuf* src = &_src;
+ struct pldm_msgbuf _dst;
+ struct pldm_msgbuf* dst = &_dst;
+
+ char buf[sizeof(msg) + 1] = {};
+
+ ASSERT_EQ(pldm_msgbuf_init_errno(src, 0, msg, sizeof(msg)), 0);
+ ASSERT_EQ(pldm_msgbuf_init_errno(dst, 0, buf, sizeof(buf)), 0);
+ EXPECT_EQ(pldm_msgbuf_copy_string_utf16(dst, src), 0);
+ ASSERT_EQ(pldm_msgbuf_destroy(dst), 0);
+ ASSERT_EQ(pldm_msgbuf_destroy(src), 0);
+ EXPECT_EQ(0, memcmp(buf, msg, sizeof(msg)));
+}
+
+TEST(msgbuf, pldm_msgbuf_copy_utf16_src_exceeds_dst)
+{
+ const char16_t msg[] = u"this is a message";
+
+ struct pldm_msgbuf _src;
+ struct pldm_msgbuf* src = &_src;
+ struct pldm_msgbuf _dst;
+ struct pldm_msgbuf* dst = &_dst;
+
+ char buf[sizeof(msg) - 1] = {};
+
+ ASSERT_EQ(pldm_msgbuf_init_errno(src, 0, msg, sizeof(msg)), 0);
+ ASSERT_EQ(pldm_msgbuf_init_errno(dst, 0, buf, sizeof(buf)), 0);
+ EXPECT_EQ(pldm_msgbuf_copy_string_utf16(dst, src), -EOVERFLOW);
+ ASSERT_EQ(pldm_msgbuf_destroy(dst), -EOVERFLOW);
+ ASSERT_EQ(pldm_msgbuf_destroy(src), 0);
+}
+
+TEST(msgbuf, pldm_msgbuf_copy_utf16_unterminated_src)
+{
+ const char16_t msg[] = {u'a'};
+
+ struct pldm_msgbuf _src;
+ struct pldm_msgbuf* src = &_src;
+ struct pldm_msgbuf _dst;
+ struct pldm_msgbuf* dst = &_dst;
+
+ char buf[sizeof(msg)] = {};
+
+ ASSERT_EQ(pldm_msgbuf_init_errno(src, 0, msg, sizeof(msg)), 0);
+ ASSERT_EQ(pldm_msgbuf_init_errno(dst, 0, buf, sizeof(buf)), 0);
+ EXPECT_EQ(pldm_msgbuf_copy_string_utf16(dst, src), -EOVERFLOW);
+ ASSERT_EQ(pldm_msgbuf_destroy(dst), 0);
+ ASSERT_EQ(pldm_msgbuf_destroy(src), -EOVERFLOW);
+}