msgbuf: Enable pldm_msgbuf_extract() into packed members

`pldm_msgbuf_extract()` should work correctly regardless of whether the
`dst` argument is a member of a packed or padded struct.

To get there while still achieving type safety we have to jump through
some hoops. Commentary in the patch hopefully captures many of them, but
a side-effect of the hoop-jumping is a couple of changes to ergonomics
of the msgbuf API:

1. `pldm_msgbuf_extract()` no-longer requires that the `dst`
   argument be a pointer. Instead, it must be an lvalue, removing all
   the `&<lvalue>` noise from the call-sites.

2. However, unfortunately the generic extraction macro has been split in
   two. We now have:

   2.1 `pldm_msgbuf_extract()`, and
   2.2 `pldm_msgbuf_extract_p()`, for when the reference we already have
        for the `dst` object is a pointer and not an lvalue.

The split was necessary because I couldn't get GCC and Clang to play
nice with differences required in the assignment expression for lvalue
and pointer type-names in the one macro. Whilst it causes a bunch of
churn it isn't a great concern as the APIs are purely internal to the
library implementation.

Change-Id: Ifc5440a5b838a48bb84c881ec334d9e145365edb
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
diff --git a/src/compiler.h b/src/compiler.h
new file mode 100644
index 0000000..31eeff9
--- /dev/null
+++ b/src/compiler.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
+#ifndef PLDM_COMPILER_H
+#define PLDM_COMPILER_H
+
+// NOLINTBEGIN(bugprone-macro-parentheses)
+/**
+ * Require that the given object is of the specified type.
+ *
+ * If the object is not of the required type then a diagnostic will be emitted.
+ *
+ * If you are reading this documentation due to hitting a compilation error
+ * passing through the macro, then you have a type error in your code that must
+ * be fixed. Despite the compiler output, the error is _not_ that some array
+ * is negatively sized, the array is negatively sized _because_ you have a type
+ * error.
+ *
+ * How this works:
+ *
+ * If the type of @p obj is not equivalent to the provided type @p type then
+ * we force the compiler to evaluate sizeof on a negatively-sized array. The
+ * C standard requires that the integer constant expression that specifies
+ * the array length must be greater than zero. Failure to meet this constraint
+ * generally terminates compilation of the translation unit as any other result
+ * cannot be handled in a sensible way. The array size is derived to an integer
+ * constant expression from a type eqivalence evaluated using _Generic()
+ * allowing us to stay within the language standard. The default generic
+ * association, representing a type mismatch, yields -1.
+ *
+ * pldm_require_obj_type() was introduced into the libpldm implementation to
+ * enable use of the pldm_msgbuf_extract*() APIs for objects that may or may not
+ * reside in a packed struct. See src/msgbuf.h for more details.
+ *
+ * @param obj The name of the object to evaluate
+ * @param type The required type of @p obj
+ *
+ * @return The expression either yields 1, or compilation is terminated
+ */
+#define pldm_require_obj_type(obj, type)                                       \
+	((void)(sizeof(                                                        \
+		struct { char buf[_Generic((obj), type: 1, default: -1)]; })))
+// NOLINTEND(bugprone-macro-parentheses)
+
+#endif
diff --git a/src/msgbuf.h b/src/msgbuf.h
index b32daf0..85cfb39 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -2,6 +2,32 @@
 #ifndef PLDM_MSGBUF_H
 #define PLDM_MSGBUF_H
 
+/*
+ * Historically, many of the structs exposed in libpldm's public headers are
+ * defined with __attribute__((packed)). This is unfortunate: it gives the
+ * impression that a wire-format buffer can be cast to the message type to make
+ * the message's fields easily accessible. As it turns out, that's not
+ * that's valid for several reasons:
+ *
+ * 1. Casting the wire-format buffer to a struct of the message type doesn't
+ *    abstract the endianness of message field values
+ *
+ * 2. Some messages contain packed tagged union fields which cannot be properly
+ *    described in a C struct.
+ *
+ * The msgbuf APIs exist to assist with (un)packing the wire-format in a way
+ * that is type-safe, spatially memory-safe, endian-safe, performant, and
+ * free of undefined-behaviour. Message structs that are added to the public
+ * library API should no-longer be marked __attribute__((packed)), and the
+ * implementation of their encode and decode functions must exploit the msgbuf
+ * API.
+ *
+ * However, we would like to allow implementation of codec functions in terms of
+ * msgbuf APIs even if they're decoding a message into a (historically) packed
+ * struct. Some of the complexity that follows is a consequence of the packed/
+ * unpacked conflict.
+ */
+
 #ifdef __cplusplus
 /*
  * Fix up C11's _Static_assert() vs C++'s static_assert().
@@ -16,10 +42,13 @@
 #include <libpldm/base.h>
 #include <libpldm/pldm_types.h>
 
+#include "compiler.h"
+
 #include <assert.h>
 #include <endian.h>
 #include <limits.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <string.h>
 #include <sys/types.h>
 
@@ -158,6 +187,93 @@
 	return consumed;
 }
 
+/*
+ * Exploit the pre-processor to perform type checking by macro substitution.
+ *
+ * A C type is defined by its alignment as well as its object
+ * size, and compilers have a hammer to enforce it in the form of
+ * `-Waddress-of-packed-member`. Due to the unpacked/packed struct conflict in
+ * the libpldm public API this presents a problem: Naively attempting to use the
+ * msgbuf APIs on a member of a packed struct would yield an error.
+ *
+ * The msgbuf APIs are implemented such that data is moved through unaligned
+ * pointers in a safe way, but to mitigate `-Waddress-of-packed-member` we must
+ * make the object pointers take a trip through `void *` at its API boundary.
+ * That presents a bit too much of an opportunity to non-surgically remove your
+ * own foot, so here we set about doing something to mitigate that as well.
+ *
+ * pldm_msgbuf_extract_typecheck() exists to enforce pointer type correctness
+ * only for the purpose of object sizes, disregarding alignment. We have a few
+ * constraints that cause some headaches:
+ *
+ * 1. We have to perform the type-check before a call through a C function,
+ *    as the function must take the object pointer argument as `void *`.
+ *    Essentially, this constrains us to doing something with macros.
+ *
+ * 2. While libpldm is a C library, its test suite is written in C++ to take
+ *    advantage of gtest.
+ *
+ * 3. Ideally we'd do something with C's `static_assert()`, however
+ *    `static_assert()` is defined as void, and as we're constrained to macros,
+ *    using `static_assert()` would require a statement-expression
+ *
+ * 4. Currently the project is built with `-std=c17`. CPP statement-expressions
+ *    are a GNU extension. We prefer to avoid switching to `-std=gnu17` just for
+ *    the purpose of enabling statement-expressions in this one instance.
+ *
+ * 5. We can achieve a conditional build error using `pldm_require_obj_type()`,
+ *    however it's implemented in terms of `_Generic()`, which is not available
+ *    in C++.
+ *
+ * Combined this means we need separate solutions for C and C++.
+ *
+ * For C, as we don't have statement-expressions, we need to exploit some other
+ * language feature to inject a `pldm_require_obj_type()` prior to the msgbuf
+ * API function call. We also have to take care of the fact that the call-sites
+ * may be in the context of a variable assignment for error-handling purposes.
+ * The key observation is that we can use the comma operator as a sequence point
+ * to order the type check before the API call, discarding the "result" value of
+ * the type check and yielding the return value of the API call.
+ *
+ * C++ could be less of a headache than the C as we can leverage template
+ * functions. An advantage of template functions is that while their definition
+ * is driven by instantion, the definition does not appear at the source
+ * location of the instantation, which gives it a great leg-up over the problems
+ * we have in the C path. However, the use of the msgbuf APIs in the test suite
+ * still makes things somewhat tricky, as the call-sites in the test suite are
+ * wrapped up in EXPECT_*() gtest macros. Ideally we'd implement functions that
+ * takes both the object type and the required type as template arguments, and
+ * then define the object pointer parameter as `void *` for a call through to
+ * the appropriate msgbuf API. However, because the msgbuf API call-sites are
+ * encapsulated in gtest macros, use of commas in the template specification
+ * causes pre-processor confusion. In this way we're constrained to only one
+ * template argument per function.
+ *
+ * Implement the C++ path using template functions that take the destination
+ * object type as a template argument, while the name of the function symbols
+ * are derived from the required type. The manual implementations of these
+ * appear at the end of the header. The type safety is actually enforced
+ * by `static_assert()` this time, as we can use statements as we're not
+ * constrained to an expression in the templated function body.
+ *
+ * The invocations of pldm_msgbuf_extract_typecheck() typically result in
+ * double-evaluation of some arguments. We're not yet bothered by this for two
+ * reasons:
+ *
+ * 1. The nature of the current call-sites are such that there are no
+ *    argument expressions that result in undesirable side-effects
+ *
+ * 2. It's an API internal to the libpldm implementation, and we can fix things
+ *    whenever something crops up the violates the observation in 1.
+ */
+#ifdef __cplusplus
+#define pldm_msgbuf_extract_typecheck(ty, fn, dst, ...)                        \
+	pldm_msgbuf_typecheck_##ty<decltype(dst)>(__VA_ARGS__)
+#else
+#define pldm_msgbuf_extract_typecheck(ty, fn, dst, ...)                        \
+	(pldm_require_obj_type(dst, ty), fn(__VA_ARGS__))
+#endif
+
 /**
  * @brief pldm_msgbuf extractor for a uint8_t
  *
@@ -168,43 +284,55 @@
  * PLDM_ERROR_INVALID_LENGTH otherwise.
  * PLDM_ERROR_INVALID_DATA if input a invalid ctx
  */
-static inline int pldm_msgbuf_extract_uint8(struct pldm_msgbuf *ctx,
-					    uint8_t *dst)
+#define pldm_msgbuf_extract_uint8(ctx, dst)                                    \
+	pldm_msgbuf_extract_typecheck(uint8_t, pldm__msgbuf_extract_uint8,     \
+				      dst, ctx, dst)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_extract_uint8(struct pldm_msgbuf *ctx, void *dst)
 {
 	if (!ctx || !ctx->cursor || !dst) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	ctx->remaining -= sizeof(*dst);
+	ctx->remaining -= sizeof(uint8_t);
 	assert(ctx->remaining >= 0);
 	if (ctx->remaining < 0) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
-	*dst = *((uint8_t *)(ctx->cursor));
+	memcpy(dst, ctx->cursor, sizeof(uint8_t));
+
 	ctx->cursor++;
 	return PLDM_SUCCESS;
 }
 
-static inline int pldm_msgbuf_extract_int8(struct pldm_msgbuf *ctx, int8_t *dst)
+#define pldm_msgbuf_extract_int8(ctx, dst)                                     \
+	pldm_msgbuf_extract_typecheck(int8_t, pldm__msgbuf_extract_int8, dst,  \
+				      ctx, dst)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_extract_int8(struct pldm_msgbuf *ctx, void *dst)
 {
 	if (!ctx || !ctx->cursor || !dst) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	ctx->remaining -= sizeof(*dst);
+	ctx->remaining -= sizeof(int8_t);
 	assert(ctx->remaining >= 0);
 	if (ctx->remaining < 0) {
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
-	*dst = *((int8_t *)(ctx->cursor));
+	memcpy(dst, ctx->cursor, sizeof(int8_t));
 	ctx->cursor++;
 	return PLDM_SUCCESS;
 }
 
-static inline int pldm_msgbuf_extract_uint16(struct pldm_msgbuf *ctx,
-					     uint16_t *dst)
+#define pldm_msgbuf_extract_uint16(ctx, dst)                                   \
+	pldm_msgbuf_extract_typecheck(uint16_t, pldm__msgbuf_extract_uint16,   \
+				      dst, ctx, dst)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_extract_uint16(struct pldm_msgbuf *ctx,
+					      void *dst)
 {
 	uint16_t ldst;
 
@@ -230,14 +358,21 @@
 	memcpy(&ldst, ctx->cursor, sizeof(ldst));
 
 	// Only assign the target value once it's correctly decoded
-	*dst = le16toh(ldst);
+	ldst = le16toh(ldst);
+
+	// Allow storing to unaligned
+	memcpy(dst, &ldst, sizeof(ldst));
+
 	ctx->cursor += sizeof(ldst);
 
 	return PLDM_SUCCESS;
 }
 
-static inline int pldm_msgbuf_extract_int16(struct pldm_msgbuf *ctx,
-					    int16_t *dst)
+#define pldm_msgbuf_extract_int16(ctx, dst)                                    \
+	pldm_msgbuf_extract_typecheck(int16_t, pldm__msgbuf_extract_int16,     \
+				      dst, ctx, dst)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_extract_int16(struct pldm_msgbuf *ctx, void *dst)
 {
 	int16_t ldst;
 
@@ -253,14 +388,19 @@
 
 	memcpy(&ldst, ctx->cursor, sizeof(ldst));
 
-	*dst = le16toh(ldst);
+	ldst = le16toh(ldst);
+	memcpy(dst, &ldst, sizeof(ldst));
 	ctx->cursor += sizeof(ldst);
 
 	return PLDM_SUCCESS;
 }
 
-static inline int pldm_msgbuf_extract_uint32(struct pldm_msgbuf *ctx,
-					     uint32_t *dst)
+#define pldm_msgbuf_extract_uint32(ctx, dst)                                   \
+	pldm_msgbuf_extract_typecheck(uint32_t, pldm__msgbuf_extract_uint32,   \
+				      dst, ctx, dst)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_extract_uint32(struct pldm_msgbuf *ctx,
+					      void *dst)
 {
 	uint32_t ldst;
 
@@ -276,14 +416,18 @@
 
 	memcpy(&ldst, ctx->cursor, sizeof(ldst));
 
-	*dst = le32toh(ldst);
+	ldst = le32toh(ldst);
+	memcpy(dst, &ldst, sizeof(ldst));
 	ctx->cursor += sizeof(ldst);
 
 	return PLDM_SUCCESS;
 }
 
-static inline int pldm_msgbuf_extract_int32(struct pldm_msgbuf *ctx,
-					    int32_t *dst)
+#define pldm_msgbuf_extract_int32(ctx, dst)                                    \
+	pldm_msgbuf_extract_typecheck(int32_t, pldm__msgbuf_extract_int32,     \
+				      dst, ctx, dst)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_extract_int32(struct pldm_msgbuf *ctx, void *dst)
 {
 	int32_t ldst;
 
@@ -299,17 +443,25 @@
 
 	memcpy(&ldst, ctx->cursor, sizeof(ldst));
 
-	*dst = le32toh(ldst);
+	ldst = le32toh(ldst);
+	memcpy(dst, &ldst, sizeof(ldst));
 	ctx->cursor += sizeof(ldst);
 
 	return PLDM_SUCCESS;
 }
 
-static inline int pldm_msgbuf_extract_real32(struct pldm_msgbuf *ctx,
-					     real32_t *dst)
+#define pldm_msgbuf_extract_real32(ctx, dst)                                   \
+	pldm_msgbuf_extract_typecheck(real32_t, pldm__msgbuf_extract_real32,   \
+				      dst, ctx, dst)
+// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
+static inline int pldm__msgbuf_extract_real32(struct pldm_msgbuf *ctx,
+					      void *dst)
 {
 	uint32_t ldst;
 
+	_Static_assert(sizeof(real32_t) == sizeof(ldst),
+		       "Mismatched type sizes for dst and ldst");
+
 	if (!ctx || !ctx->cursor || !dst) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
@@ -320,25 +472,51 @@
 		return PLDM_ERROR_INVALID_LENGTH;
 	}
 
-	_Static_assert(sizeof(*dst) == sizeof(ldst),
-		       "Mismatched type sizes for dst and ldst");
 	memcpy(&ldst, ctx->cursor, sizeof(ldst));
 	ldst = le32toh(ldst);
-	memcpy(dst, &ldst, sizeof(*dst));
-	ctx->cursor += sizeof(*dst);
+	memcpy(dst, &ldst, sizeof(ldst));
+	ctx->cursor += sizeof(ldst);
 
 	return PLDM_SUCCESS;
 }
 
+/**
+ * Extract the field at the msgbuf cursor into the lvalue named by dst.
+ *
+ * @param ctx The msgbuf context object
+ * @param dst The lvalue into which the field at the msgbuf cursor should be
+ *            extracted
+ *
+ * @return PLDM_SUCCESS on success, otherwise another value on error
+ */
 #define pldm_msgbuf_extract(ctx, dst)                                          \
-	_Generic((*(dst)),                                                     \
-		uint8_t: pldm_msgbuf_extract_uint8,                            \
-		int8_t: pldm_msgbuf_extract_int8,                              \
-		uint16_t: pldm_msgbuf_extract_uint16,                          \
-		int16_t: pldm_msgbuf_extract_int16,                            \
-		uint32_t: pldm_msgbuf_extract_uint32,                          \
-		int32_t: pldm_msgbuf_extract_int32,                            \
-		real32_t: pldm_msgbuf_extract_real32)(ctx, dst)
+	_Generic((dst),                                                        \
+		uint8_t: pldm__msgbuf_extract_uint8,                           \
+		int8_t: pldm__msgbuf_extract_int8,                             \
+		uint16_t: pldm__msgbuf_extract_uint16,                         \
+		int16_t: pldm__msgbuf_extract_int16,                           \
+		uint32_t: pldm__msgbuf_extract_uint32,                         \
+		int32_t: pldm__msgbuf_extract_int32,                           \
+		real32_t: pldm__msgbuf_extract_real32)(ctx, (void *)&(dst))
+
+/**
+ * Extract the field at the msgbuf cursor into the object pointed-to by dst.
+ *
+ * @param ctx The msgbuf context object
+ * @param dst The pointer to the object into which the field at the msgbuf
+ *            cursor should be extracted
+ *
+ * @return PLDM_SUCCESS on success, otherwise another value on error
+ */
+#define pldm_msgbuf_extract_p(ctx, dst)                                        \
+	_Generic((dst),                                                        \
+		uint8_t *: pldm__msgbuf_extract_uint8,                         \
+		int8_t *: pldm__msgbuf_extract_int8,                           \
+		uint16_t *: pldm__msgbuf_extract_uint16,                       \
+		int16_t *: pldm__msgbuf_extract_int16,                         \
+		uint32_t *: pldm__msgbuf_extract_uint32,                       \
+		int32_t *: pldm__msgbuf_extract_int32,                         \
+		real32_t *: pldm__msgbuf_extract_real32)(ctx, dst)
 
 static inline int pldm_msgbuf_extract_array_uint8(struct pldm_msgbuf *ctx,
 						  uint8_t *dst, size_t count)
@@ -580,4 +758,64 @@
 }
 #endif
 
+#ifdef __cplusplus
+#include <type_traits>
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_uint8_t(struct pldm_msgbuf *ctx,
+						void *buf)
+{
+	static_assert(std::is_same<uint8_t *, T>::value);
+	return pldm__msgbuf_extract_uint8(ctx, buf);
+}
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_int8_t(struct pldm_msgbuf *ctx,
+					       void *buf)
+{
+	static_assert(std::is_same<int8_t *, T>::value);
+	return pldm__msgbuf_extract_int8(ctx, buf);
+}
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_uint16_t(struct pldm_msgbuf *ctx,
+						 void *buf)
+{
+	static_assert(std::is_same<uint16_t *, T>::value);
+	return pldm__msgbuf_extract_uint16(ctx, buf);
+}
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_int16_t(struct pldm_msgbuf *ctx,
+						void *buf)
+{
+	static_assert(std::is_same<int16_t *, T>::value);
+	return pldm__msgbuf_extract_int16(ctx, buf);
+}
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_uint32_t(struct pldm_msgbuf *ctx,
+						 void *buf)
+{
+	static_assert(std::is_same<uint32_t *, T>::value);
+	return pldm__msgbuf_extract_uint32(ctx, buf);
+}
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_int32_t(struct pldm_msgbuf *ctx,
+						void *buf)
+{
+	static_assert(std::is_same<int32_t *, T>::value);
+	return pldm__msgbuf_extract_int32(ctx, buf);
+}
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_real32_t(struct pldm_msgbuf *ctx,
+						 void *buf)
+{
+	static_assert(std::is_same<real32_t *, T>::value);
+	return pldm__msgbuf_extract_real32(ctx, buf);
+}
+#endif
+
 #endif /* BUF_H */
diff --git a/src/msgbuf/platform.h b/src/msgbuf/platform.h
index 217962e..7ca36c9 100644
--- a/src/msgbuf/platform.h
+++ b/src/msgbuf/platform.h
@@ -10,11 +10,11 @@
 pldm_msgbuf_extract_value_pdr_hdr(struct pldm_msgbuf *ctx,
 				  struct pldm_value_pdr_hdr *hdr)
 {
-	pldm_msgbuf_extract(ctx, &hdr->record_handle);
-	pldm_msgbuf_extract(ctx, &hdr->version);
-	pldm_msgbuf_extract(ctx, &hdr->type);
-	pldm_msgbuf_extract(ctx, &hdr->record_change_num);
-	pldm_msgbuf_extract(ctx, &hdr->length);
+	pldm_msgbuf_extract(ctx, hdr->record_handle);
+	pldm_msgbuf_extract(ctx, hdr->version);
+	pldm_msgbuf_extract(ctx, hdr->type);
+	pldm_msgbuf_extract(ctx, hdr->record_change_num);
+	pldm_msgbuf_extract(ctx, hdr->length);
 
 	return pldm_msgbuf_validate(ctx);
 }
@@ -33,17 +33,17 @@
 {
 	switch (tag) {
 	case PLDM_SENSOR_DATA_SIZE_UINT8:
-		return pldm_msgbuf_extract(ctx, &dst->value_u8);
+		return pldm_msgbuf_extract(ctx, dst->value_u8);
 	case PLDM_SENSOR_DATA_SIZE_SINT8:
-		return pldm_msgbuf_extract(ctx, &dst->value_s8);
+		return pldm_msgbuf_extract(ctx, dst->value_s8);
 	case PLDM_SENSOR_DATA_SIZE_UINT16:
-		return pldm_msgbuf_extract(ctx, &dst->value_u16);
+		return pldm_msgbuf_extract(ctx, dst->value_u16);
 	case PLDM_SENSOR_DATA_SIZE_SINT16:
-		return pldm_msgbuf_extract(ctx, &dst->value_s16);
+		return pldm_msgbuf_extract(ctx, dst->value_s16);
 	case PLDM_SENSOR_DATA_SIZE_UINT32:
-		return pldm_msgbuf_extract(ctx, &dst->value_u32);
+		return pldm_msgbuf_extract(ctx, dst->value_u32);
 	case PLDM_SENSOR_DATA_SIZE_SINT32:
-		return pldm_msgbuf_extract(ctx, &dst->value_s32);
+		return pldm_msgbuf_extract(ctx, dst->value_s32);
 	}
 
 	return -PLDM_ERROR_INVALID_DATA;
@@ -57,46 +57,64 @@
 __attribute__((always_inline)) static inline int
 pldm_msgbuf_extract_sensor_value(struct pldm_msgbuf *ctx,
 				 enum pldm_sensor_readings_data_type tag,
-				 uint8_t *val)
+				 void *val)
 {
 	switch (tag) {
 	case PLDM_SENSOR_DATA_SIZE_UINT8:
-		return pldm_msgbuf_extract_uint8(ctx, (uint8_t *)val);
+		return pldm__msgbuf_extract_uint8(ctx, val);
 	case PLDM_SENSOR_DATA_SIZE_SINT8:
-		return pldm_msgbuf_extract_int8(ctx, (int8_t *)val);
+		return pldm__msgbuf_extract_int8(ctx, val);
 	case PLDM_SENSOR_DATA_SIZE_UINT16:
-		return pldm_msgbuf_extract_uint16(ctx, (uint16_t *)val);
+		return pldm__msgbuf_extract_uint16(ctx, val);
 	case PLDM_SENSOR_DATA_SIZE_SINT16:
-		return pldm_msgbuf_extract_int16(ctx, (int16_t *)val);
+		return pldm__msgbuf_extract_int16(ctx, val);
 	case PLDM_SENSOR_DATA_SIZE_UINT32:
-		return pldm_msgbuf_extract_uint32(ctx, (uint32_t *)val);
+		return pldm__msgbuf_extract_uint32(ctx, val);
 	case PLDM_SENSOR_DATA_SIZE_SINT32:
-		return pldm_msgbuf_extract_int32(ctx, (int32_t *)val);
+		return pldm__msgbuf_extract_int32(ctx, val);
 	}
 
 	return -PLDM_ERROR_INVALID_DATA;
 }
 
+#define pldm_msgbuf_extract_range_field_format(ctx, tag, dst)                  \
+	pldm_msgbuf_extract_typecheck(union_range_field_format,                \
+				      pldm__msgbuf_extract_range_field_format, \
+				      dst, ctx, tag, (void *)&(dst))
 __attribute__((always_inline)) static inline int
-pldm_msgbuf_extract_range_field_format(struct pldm_msgbuf *ctx,
-				       enum pldm_range_field_format tag,
-				       union_range_field_format *dst)
+pldm__msgbuf_extract_range_field_format(struct pldm_msgbuf *ctx,
+					enum pldm_range_field_format tag,
+					void *rff)
 {
 	switch (tag) {
 	case PLDM_RANGE_FIELD_FORMAT_UINT8:
-		return pldm_msgbuf_extract(ctx, &dst->value_u8);
+		return pldm__msgbuf_extract_uint8(
+			ctx, ((char *)rff) + offsetof(union_range_field_format,
+						      value_u8));
 	case PLDM_RANGE_FIELD_FORMAT_SINT8:
-		return pldm_msgbuf_extract(ctx, &dst->value_s8);
+		return pldm__msgbuf_extract_int8(
+			ctx, ((char *)rff) + offsetof(union_range_field_format,
+						      value_s8));
 	case PLDM_RANGE_FIELD_FORMAT_UINT16:
-		return pldm_msgbuf_extract(ctx, &dst->value_u16);
+		return pldm__msgbuf_extract_uint16(
+			ctx, ((char *)rff) + offsetof(union_range_field_format,
+						      value_u16));
 	case PLDM_RANGE_FIELD_FORMAT_SINT16:
-		return pldm_msgbuf_extract(ctx, &dst->value_s16);
+		return pldm__msgbuf_extract_int16(
+			ctx, ((char *)rff) + offsetof(union_range_field_format,
+						      value_s16));
 	case PLDM_RANGE_FIELD_FORMAT_UINT32:
-		return pldm_msgbuf_extract(ctx, &dst->value_u32);
+		return pldm__msgbuf_extract_uint32(
+			ctx, ((char *)rff) + offsetof(union_range_field_format,
+						      value_u32));
 	case PLDM_RANGE_FIELD_FORMAT_SINT32:
-		return pldm_msgbuf_extract(ctx, &dst->value_s32);
+		return pldm__msgbuf_extract_int32(
+			ctx, ((char *)rff) + offsetof(union_range_field_format,
+						      value_s32));
 	case PLDM_RANGE_FIELD_FORMAT_REAL32:
-		return pldm_msgbuf_extract(ctx, &dst->value_f32);
+		return pldm__msgbuf_extract_real32(
+			ctx, ((char *)rff) + offsetof(union_range_field_format,
+						      value_f32));
 	}
 
 	return -PLDM_ERROR_INVALID_DATA;
@@ -105,25 +123,36 @@
 /* This API is bad, but it's because the caller's APIs are also bad */
 __attribute__((always_inline)) static inline int
 pldm_msgbuf_extract_effecter_value(struct pldm_msgbuf *ctx,
-				   enum pldm_effecter_data_size tag,
-				   uint8_t *val)
+				   enum pldm_effecter_data_size tag, void *dst)
 {
 	switch (tag) {
 	case PLDM_EFFECTER_DATA_SIZE_UINT8:
-		return pldm_msgbuf_extract_uint8(ctx, (uint8_t *)val);
+		return pldm__msgbuf_extract_uint8(ctx, dst);
 	case PLDM_EFFECTER_DATA_SIZE_SINT8:
-		return pldm_msgbuf_extract_int8(ctx, (int8_t *)val);
+		return pldm__msgbuf_extract_int8(ctx, dst);
 	case PLDM_EFFECTER_DATA_SIZE_UINT16:
-		return pldm_msgbuf_extract_uint16(ctx, (uint16_t *)val);
+		return pldm__msgbuf_extract_uint16(ctx, dst);
 	case PLDM_EFFECTER_DATA_SIZE_SINT16:
-		return pldm_msgbuf_extract_int16(ctx, (int16_t *)val);
+		return pldm__msgbuf_extract_int16(ctx, dst);
 	case PLDM_EFFECTER_DATA_SIZE_UINT32:
-		return pldm_msgbuf_extract_uint32(ctx, (uint32_t *)val);
+		return pldm__msgbuf_extract_uint32(ctx, dst);
 	case PLDM_EFFECTER_DATA_SIZE_SINT32:
-		return pldm_msgbuf_extract_int32(ctx, (int32_t *)val);
+		return pldm__msgbuf_extract_int32(ctx, dst);
 	}
 
 	return -PLDM_ERROR_INVALID_DATA;
 }
 
+#ifdef __cplusplus
+#include <type_traits>
+
+template <typename T>
+static inline int pldm_msgbuf_typecheck_range_field_format(
+	struct pldm_msgbuf *ctx, enum pldm_range_field_format tag, void *_rff)
+{
+	static_assert(std::is_same<union_range_field_format, T>::value);
+	return pldm__msgbuf_extract_range_field_format(ctx, tag, _rff);
+}
+#endif
+
 #endif
diff --git a/src/oem/meta/file_io.c b/src/oem/meta/file_io.c
index ab6c7a6..0495ac5 100644
--- a/src/oem/meta/file_io.c
+++ b/src/oem/meta/file_io.c
@@ -26,8 +26,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, file_handle);
-	pldm_msgbuf_extract(buf, length);
+	pldm_msgbuf_extract_p(buf, file_handle);
+	pldm_msgbuf_extract_p(buf, length);
 	pldm_msgbuf_extract_array_uint8(buf, data, *length);
 
 	return pldm_msgbuf_destroy_consumed(buf);
diff --git a/src/platform.c b/src/platform.c
index 1bd7889..6f7b940 100644
--- a/src/platform.c
+++ b/src/platform.c
@@ -276,16 +276,16 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, effecter_id);
-	pldm_msgbuf_extract(buf, comp_effecter_count);
+	pldm_msgbuf_extract_p(buf, effecter_id);
+	pldm_msgbuf_extract_p(buf, comp_effecter_count);
 
 	if (*comp_effecter_count > 8) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
 	for (i = 0; i < *comp_effecter_count; i++) {
-		pldm_msgbuf_extract(buf, &field[i].set_request);
-		pldm_msgbuf_extract(buf, &field[i].effecter_state);
+		pldm_msgbuf_extract(buf, field[i].set_request);
+		pldm_msgbuf_extract(buf, field[i].effecter_state);
 	}
 
 	return pldm_msgbuf_destroy(buf);
@@ -317,11 +317,11 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, record_hndl);
-	pldm_msgbuf_extract(buf, data_transfer_hndl);
-	pldm_msgbuf_extract(buf, transfer_op_flag);
-	pldm_msgbuf_extract(buf, request_cnt);
-	pldm_msgbuf_extract(buf, record_chg_num);
+	pldm_msgbuf_extract_p(buf, record_hndl);
+	pldm_msgbuf_extract_p(buf, data_transfer_hndl);
+	pldm_msgbuf_extract_p(buf, transfer_op_flag);
+	pldm_msgbuf_extract_p(buf, request_cnt);
+	pldm_msgbuf_extract_p(buf, record_chg_num);
 
 	return pldm_msgbuf_destroy(buf);
 }
@@ -445,22 +445,22 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, completion_code);
+	pldm_msgbuf_extract_p(buf, completion_code);
 	if (PLDM_SUCCESS != *completion_code) {
 		return PLDM_SUCCESS;
 	}
 
-	pldm_msgbuf_extract(buf, repository_state);
+	pldm_msgbuf_extract_p(buf, repository_state);
 	if (*repository_state > PLDM_FAILED) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
 	pldm_msgbuf_extract_array(buf, update_time, PLDM_TIMESTAMP104_SIZE);
 	pldm_msgbuf_extract_array(buf, oem_update_time, PLDM_TIMESTAMP104_SIZE);
-	pldm_msgbuf_extract(buf, record_count);
-	pldm_msgbuf_extract(buf, repository_size);
-	pldm_msgbuf_extract(buf, largest_record_size);
-	pldm_msgbuf_extract(buf, data_transfer_handle_timeout);
+	pldm_msgbuf_extract_p(buf, record_count);
+	pldm_msgbuf_extract_p(buf, repository_size);
+	pldm_msgbuf_extract_p(buf, largest_record_size);
+	pldm_msgbuf_extract_p(buf, data_transfer_handle_timeout);
 
 	return pldm_msgbuf_destroy(buf);
 }
@@ -525,15 +525,15 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, completion_code);
+	pldm_msgbuf_extract_p(buf, completion_code);
 	if (PLDM_SUCCESS != *completion_code) {
 		return PLDM_SUCCESS;
 	}
 
-	pldm_msgbuf_extract(buf, next_record_hndl);
-	pldm_msgbuf_extract(buf, next_data_transfer_hndl);
-	pldm_msgbuf_extract(buf, transfer_flag);
-	rc = pldm_msgbuf_extract(buf, resp_cnt);
+	pldm_msgbuf_extract_p(buf, next_record_hndl);
+	pldm_msgbuf_extract_p(buf, next_data_transfer_hndl);
+	pldm_msgbuf_extract_p(buf, transfer_flag);
+	rc = pldm_msgbuf_extract_p(buf, resp_cnt);
 	if (rc) {
 		return rc;
 	}
@@ -546,7 +546,7 @@
 	}
 
 	if (*transfer_flag == PLDM_END) {
-		pldm_msgbuf_extract(buf, transfer_crc);
+		pldm_msgbuf_extract_p(buf, transfer_crc);
 	}
 
 	return pldm_msgbuf_destroy(buf);
@@ -575,8 +575,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, effecter_id);
-	rc = pldm_msgbuf_extract(buf, effecter_data_size);
+	pldm_msgbuf_extract_p(buf, effecter_id);
+	rc = pldm_msgbuf_extract_p(buf, effecter_data_size);
 	if (rc) {
 		return PLDM_ERROR_INVALID_DATA;
 	}
@@ -796,7 +796,7 @@
 		return rc;
 	}
 
-	rc = pldm_msgbuf_extract(buf, completion_code);
+	rc = pldm_msgbuf_extract_p(buf, completion_code);
 	if (rc) {
 		return rc;
 	}
@@ -805,7 +805,7 @@
 		return PLDM_SUCCESS;
 	}
 
-	rc = pldm_msgbuf_extract(buf, comp_sensor_count);
+	rc = pldm_msgbuf_extract_p(buf, comp_sensor_count);
 	if (rc) {
 		return rc;
 	}
@@ -815,10 +815,10 @@
 	}
 
 	for (i = 0; i < *comp_sensor_count; i++) {
-		pldm_msgbuf_extract(buf, &field[i].sensor_op_state);
-		pldm_msgbuf_extract(buf, &field[i].present_state);
-		pldm_msgbuf_extract(buf, &field[i].previous_state);
-		pldm_msgbuf_extract(buf, &field[i].event_state);
+		pldm_msgbuf_extract(buf, field[i].sensor_op_state);
+		pldm_msgbuf_extract(buf, field[i].present_state);
+		pldm_msgbuf_extract(buf, field[i].previous_state);
+		pldm_msgbuf_extract(buf, field[i].event_state);
 	}
 
 	return pldm_msgbuf_destroy_consumed(buf);
@@ -845,9 +845,9 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, sensor_id);
-	pldm_msgbuf_extract(buf, &sensor_rearm->byte);
-	pldm_msgbuf_extract(buf, reserved);
+	pldm_msgbuf_extract_p(buf, sensor_id);
+	pldm_msgbuf_extract(buf, sensor_rearm->byte);
+	pldm_msgbuf_extract_p(buf, reserved);
 
 	return pldm_msgbuf_destroy(buf);
 }
@@ -910,9 +910,9 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, format_version);
-	pldm_msgbuf_extract(buf, tid);
-	pldm_msgbuf_extract(buf, event_class);
+	pldm_msgbuf_extract_p(buf, format_version);
+	pldm_msgbuf_extract_p(buf, tid);
+	pldm_msgbuf_extract_p(buf, event_class);
 	*event_data_offset =
 		sizeof(*format_version) + sizeof(*tid) + sizeof(*event_class);
 
@@ -940,8 +940,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, format_version);
-	rc = pldm_msgbuf_extract(buf, transfer_operation_flag);
+	pldm_msgbuf_extract_p(buf, format_version);
+	rc = pldm_msgbuf_extract_p(buf, transfer_operation_flag);
 	if (rc) {
 		return rc;
 	}
@@ -949,8 +949,8 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	pldm_msgbuf_extract(buf, data_transfer_handle);
-	rc = pldm_msgbuf_extract(buf, event_id_to_acknowledge);
+	pldm_msgbuf_extract_p(buf, data_transfer_handle);
+	rc = pldm_msgbuf_extract_p(buf, event_id_to_acknowledge);
 	if (rc) {
 		return rc;
 	}
@@ -1136,7 +1136,7 @@
 		return rc;
 	}
 
-	rc = pldm_msgbuf_extract(buf, completion_code);
+	rc = pldm_msgbuf_extract_p(buf, completion_code);
 	if (rc) {
 		return rc;
 	}
@@ -1145,7 +1145,7 @@
 		return PLDM_SUCCESS;
 	}
 
-	rc = pldm_msgbuf_extract(buf, platform_event_status);
+	rc = pldm_msgbuf_extract_p(buf, platform_event_status);
 	if (rc) {
 		return rc;
 	}
@@ -1202,7 +1202,7 @@
 		return rc;
 	}
 
-	rc = pldm_msgbuf_extract(buf, completion_code);
+	rc = pldm_msgbuf_extract_p(buf, completion_code);
 	if (rc) {
 		return rc;
 	}
@@ -1211,7 +1211,7 @@
 		return PLDM_SUCCESS;
 	}
 
-	pldm_msgbuf_extract(buf, terminus_max_buffer_size);
+	pldm_msgbuf_extract_p(buf, terminus_max_buffer_size);
 
 	return pldm_msgbuf_destroy_consumed(buf);
 }
@@ -1274,7 +1274,7 @@
 		return rc;
 	}
 
-	rc = pldm_msgbuf_extract(buf, completion_code);
+	rc = pldm_msgbuf_extract_p(buf, completion_code);
 	if (rc) {
 		return rc;
 	}
@@ -1283,7 +1283,7 @@
 		return PLDM_SUCCESS;
 	}
 
-	rc = pldm_msgbuf_extract(buf, synchrony_config);
+	rc = pldm_msgbuf_extract_p(buf, synchrony_config);
 	if (rc) {
 		return rc;
 	}
@@ -1292,9 +1292,9 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	pldm_msgbuf_extract(buf, &synchrony_config_support->byte);
+	pldm_msgbuf_extract_p(buf, &synchrony_config_support->byte);
 
-	rc = pldm_msgbuf_extract(buf, number_event_class_returned);
+	rc = pldm_msgbuf_extract_p(buf, number_event_class_returned);
 	if (rc) {
 		return rc;
 	}
@@ -1308,7 +1308,7 @@
 	}
 
 	for (i = 0; i < *number_event_class_returned; i++) {
-		pldm_msgbuf_extract(buf, &event_class[i]);
+		pldm_msgbuf_extract(buf, event_class[i]);
 	}
 
 	return pldm_msgbuf_destroy_consumed(buf);
@@ -1333,8 +1333,8 @@
 	size_t event_class_data_length =
 		event_data_length - PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES;
 
-	pldm_msgbuf_extract(buf, sensor_id);
-	rc = pldm_msgbuf_extract(buf, sensor_event_class_type);
+	pldm_msgbuf_extract_p(buf, sensor_id);
+	rc = pldm_msgbuf_extract_p(buf, sensor_event_class_type);
 	if (rc) {
 		return rc;
 	}
@@ -1385,8 +1385,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, present_op_state);
-	pldm_msgbuf_extract(buf, previous_op_state);
+	pldm_msgbuf_extract_p(buf, present_op_state);
+	pldm_msgbuf_extract_p(buf, previous_op_state);
 
 	return pldm_msgbuf_destroy_consumed(buf);
 }
@@ -1413,9 +1413,9 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, sensor_offset);
-	pldm_msgbuf_extract(buf, event_state);
-	pldm_msgbuf_extract(buf, previous_event_state);
+	pldm_msgbuf_extract_p(buf, sensor_offset);
+	pldm_msgbuf_extract_p(buf, event_state);
+	pldm_msgbuf_extract_p(buf, previous_event_state);
 
 	return pldm_msgbuf_destroy_consumed(buf);
 }
@@ -1448,9 +1448,9 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, event_state);
-	pldm_msgbuf_extract(buf, previous_event_state);
-	rc = pldm_msgbuf_extract(buf, sensor_data_size);
+	pldm_msgbuf_extract_p(buf, event_state);
+	pldm_msgbuf_extract_p(buf, previous_event_state);
+	rc = pldm_msgbuf_extract_p(buf, sensor_data_size);
 	if (rc) {
 		return rc;
 	}
@@ -1463,42 +1463,42 @@
 	switch (*sensor_data_size) {
 	case PLDM_SENSOR_DATA_SIZE_UINT8: {
 		uint8_t val;
-		if (!pldm_msgbuf_extract(buf, &val)) {
+		if (!pldm_msgbuf_extract(buf, val)) {
 			*present_reading = (uint32_t)val;
 		}
 		break;
 	}
 	case PLDM_SENSOR_DATA_SIZE_SINT8: {
 		int8_t val;
-		if (!pldm_msgbuf_extract(buf, &val)) {
+		if (!pldm_msgbuf_extract(buf, val)) {
 			*present_reading = (uint32_t)(int32_t)val;
 		}
 		break;
 	}
 	case PLDM_SENSOR_DATA_SIZE_UINT16: {
 		uint16_t val;
-		if (!pldm_msgbuf_extract(buf, &val)) {
+		if (!pldm_msgbuf_extract(buf, val)) {
 			*present_reading = (uint32_t)val;
 		}
 		break;
 	}
 	case PLDM_SENSOR_DATA_SIZE_SINT16: {
 		int16_t val;
-		if (!pldm_msgbuf_extract(buf, &val)) {
+		if (!pldm_msgbuf_extract(buf, val)) {
 			*present_reading = (uint32_t)(int32_t)val;
 		}
 		break;
 	}
 	case PLDM_SENSOR_DATA_SIZE_UINT32: {
 		uint32_t val;
-		if (!pldm_msgbuf_extract(buf, &val)) {
+		if (!pldm_msgbuf_extract(buf, val)) {
 			*present_reading = (uint32_t)val;
 		}
 		break;
 	}
 	case PLDM_SENSOR_DATA_SIZE_SINT32: {
 		int32_t val;
-		if (!pldm_msgbuf_extract(buf, &val)) {
+		if (!pldm_msgbuf_extract(buf, val)) {
 			*present_reading = (uint32_t)val;
 		}
 		break;
@@ -1537,25 +1537,25 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, &pdr_value->terminus_handle);
-	pldm_msgbuf_extract(buf, &pdr_value->sensor_id);
-	pldm_msgbuf_extract(buf, &pdr_value->entity_type);
-	pldm_msgbuf_extract(buf, &pdr_value->entity_instance_num);
-	pldm_msgbuf_extract(buf, &pdr_value->container_id);
-	pldm_msgbuf_extract(buf, &pdr_value->sensor_init);
-	pldm_msgbuf_extract(buf, &pdr_value->sensor_auxiliary_names_pdr);
-	pldm_msgbuf_extract(buf, &pdr_value->base_unit);
-	pldm_msgbuf_extract(buf, &pdr_value->unit_modifier);
-	pldm_msgbuf_extract(buf, &pdr_value->rate_unit);
-	pldm_msgbuf_extract(buf, &pdr_value->base_oem_unit_handle);
-	pldm_msgbuf_extract(buf, &pdr_value->aux_unit);
-	pldm_msgbuf_extract(buf, &pdr_value->aux_unit_modifier);
-	pldm_msgbuf_extract(buf, &pdr_value->aux_rate_unit);
-	pldm_msgbuf_extract(buf, &pdr_value->rel);
-	pldm_msgbuf_extract(buf, &pdr_value->aux_oem_unit_handle);
-	pldm_msgbuf_extract(buf, &pdr_value->is_linear);
+	pldm_msgbuf_extract(buf, pdr_value->terminus_handle);
+	pldm_msgbuf_extract(buf, pdr_value->sensor_id);
+	pldm_msgbuf_extract(buf, pdr_value->entity_type);
+	pldm_msgbuf_extract(buf, pdr_value->entity_instance_num);
+	pldm_msgbuf_extract(buf, pdr_value->container_id);
+	pldm_msgbuf_extract(buf, pdr_value->sensor_init);
+	pldm_msgbuf_extract(buf, pdr_value->sensor_auxiliary_names_pdr);
+	pldm_msgbuf_extract(buf, pdr_value->base_unit);
+	pldm_msgbuf_extract(buf, pdr_value->unit_modifier);
+	pldm_msgbuf_extract(buf, pdr_value->rate_unit);
+	pldm_msgbuf_extract(buf, pdr_value->base_oem_unit_handle);
+	pldm_msgbuf_extract(buf, pdr_value->aux_unit);
+	pldm_msgbuf_extract(buf, pdr_value->aux_unit_modifier);
+	pldm_msgbuf_extract(buf, pdr_value->aux_rate_unit);
+	pldm_msgbuf_extract(buf, pdr_value->rel);
+	pldm_msgbuf_extract(buf, pdr_value->aux_oem_unit_handle);
+	pldm_msgbuf_extract(buf, pdr_value->is_linear);
 
-	rc = pldm_msgbuf_extract(buf, &pdr_value->sensor_data_size);
+	rc = pldm_msgbuf_extract(buf, pdr_value->sensor_data_size);
 	if (rc) {
 		return rc;
 	}
@@ -1563,24 +1563,24 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	pldm_msgbuf_extract(buf, &pdr_value->resolution);
-	pldm_msgbuf_extract(buf, &pdr_value->offset);
-	pldm_msgbuf_extract(buf, &pdr_value->accuracy);
-	pldm_msgbuf_extract(buf, &pdr_value->plus_tolerance);
-	pldm_msgbuf_extract(buf, &pdr_value->minus_tolerance);
+	pldm_msgbuf_extract(buf, pdr_value->resolution);
+	pldm_msgbuf_extract(buf, pdr_value->offset);
+	pldm_msgbuf_extract(buf, pdr_value->accuracy);
+	pldm_msgbuf_extract(buf, pdr_value->plus_tolerance);
+	pldm_msgbuf_extract(buf, pdr_value->minus_tolerance);
 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
 					&pdr_value->hysteresis);
-	pldm_msgbuf_extract(buf, &pdr_value->supported_thresholds.byte);
+	pldm_msgbuf_extract(buf, pdr_value->supported_thresholds.byte);
 	pldm_msgbuf_extract(
-		buf, &pdr_value->threshold_and_hysteresis_volatility.byte);
-	pldm_msgbuf_extract(buf, &pdr_value->state_transition_interval);
-	pldm_msgbuf_extract(buf, &pdr_value->update_interval);
+		buf, pdr_value->threshold_and_hysteresis_volatility.byte);
+	pldm_msgbuf_extract(buf, pdr_value->state_transition_interval);
+	pldm_msgbuf_extract(buf, pdr_value->update_interval);
 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
 					&pdr_value->max_readable);
 	pldm_msgbuf_extract_sensor_data(buf, pdr_value->sensor_data_size,
 					&pdr_value->min_readable);
 
-	rc = pldm_msgbuf_extract(buf, &pdr_value->range_field_format);
+	rc = pldm_msgbuf_extract(buf, pdr_value->range_field_format);
 	if (rc) {
 		return rc;
 	}
@@ -1588,25 +1588,25 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	pldm_msgbuf_extract(buf, &pdr_value->range_field_support.byte);
+	pldm_msgbuf_extract(buf, pdr_value->range_field_support.byte);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->nominal_value);
+		buf, pdr_value->range_field_format, pdr_value->nominal_value);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->normal_max);
+		buf, pdr_value->range_field_format, pdr_value->normal_max);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->normal_min);
+		buf, pdr_value->range_field_format, pdr_value->normal_min);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->warning_high);
+		buf, pdr_value->range_field_format, pdr_value->warning_high);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->warning_low);
+		buf, pdr_value->range_field_format, pdr_value->warning_low);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->critical_high);
+		buf, pdr_value->range_field_format, pdr_value->critical_high);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->critical_low);
+		buf, pdr_value->range_field_format, pdr_value->critical_low);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->fatal_high);
+		buf, pdr_value->range_field_format, pdr_value->fatal_high);
 	pldm_msgbuf_extract_range_field_format(
-		buf, pdr_value->range_field_format, &pdr_value->fatal_low);
+		buf, pdr_value->range_field_format, pdr_value->fatal_low);
 
 	return pldm_msgbuf_destroy(buf);
 }
@@ -1738,7 +1738,7 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, effecter_id);
+	pldm_msgbuf_extract_p(buf, effecter_id);
 
 	return pldm_msgbuf_destroy_consumed(buf);
 }
@@ -1769,7 +1769,7 @@
 		return rc;
 	}
 
-	rc = pldm_msgbuf_extract(buf, completion_code);
+	rc = pldm_msgbuf_extract_p(buf, completion_code);
 	if (rc) {
 		return rc;
 	}
@@ -1778,7 +1778,7 @@
 		return PLDM_SUCCESS;
 	}
 
-	rc = pldm_msgbuf_extract(buf, effecter_data_size);
+	rc = pldm_msgbuf_extract_p(buf, effecter_data_size);
 	if (rc) {
 		return rc;
 	}
@@ -1787,7 +1787,7 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	rc = pldm_msgbuf_extract(buf, effecter_oper_state);
+	rc = pldm_msgbuf_extract_p(buf, effecter_oper_state);
 	if (rc) {
 		return rc;
 	}
@@ -1890,8 +1890,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, event_data_format);
-	pldm_msgbuf_extract(buf, number_of_change_records);
+	pldm_msgbuf_extract_p(buf, event_data_format);
+	pldm_msgbuf_extract_p(buf, number_of_change_records);
 
 	*change_record_data_offset =
 		sizeof(*event_data_format) + sizeof(*number_of_change_records);
@@ -1921,8 +1921,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, format_version);
-	rc = pldm_msgbuf_extract(buf, event_id);
+	pldm_msgbuf_extract_p(buf, format_version);
+	rc = pldm_msgbuf_extract_p(buf, event_id);
 	if (rc) {
 		return rc;
 	}
@@ -1931,7 +1931,7 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	pldm_msgbuf_extract(buf, data_transfer_handle);
+	pldm_msgbuf_extract_p(buf, data_transfer_handle);
 
 	return pldm_msgbuf_destroy_consumed(buf);
 }
@@ -1988,8 +1988,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, event_data_operation);
-	pldm_msgbuf_extract(buf, number_of_change_entries);
+	pldm_msgbuf_extract_p(buf, event_data_operation);
+	pldm_msgbuf_extract_p(buf, number_of_change_entries);
 
 	*change_entry_data_offset = sizeof(*event_data_operation) +
 				    sizeof(*number_of_change_entries);
@@ -2052,7 +2052,7 @@
 		return rc;
 	}
 
-	rc = pldm_msgbuf_extract(buf, completion_code);
+	rc = pldm_msgbuf_extract_p(buf, completion_code);
 	if (rc) {
 		return rc;
 	}
@@ -2061,7 +2061,7 @@
 		return PLDM_SUCCESS;
 	}
 
-	rc = pldm_msgbuf_extract(buf, sensor_data_size);
+	rc = pldm_msgbuf_extract_p(buf, sensor_data_size);
 	if (rc) {
 		return rc;
 	}
@@ -2070,11 +2070,11 @@
 		return PLDM_ERROR_INVALID_DATA;
 	}
 
-	pldm_msgbuf_extract(buf, sensor_operational_state);
-	pldm_msgbuf_extract(buf, sensor_event_message_enable);
-	pldm_msgbuf_extract(buf, present_state);
-	pldm_msgbuf_extract(buf, previous_state);
-	pldm_msgbuf_extract(buf, event_state);
+	pldm_msgbuf_extract_p(buf, sensor_operational_state);
+	pldm_msgbuf_extract_p(buf, sensor_event_message_enable);
+	pldm_msgbuf_extract_p(buf, present_state);
+	pldm_msgbuf_extract_p(buf, previous_state);
+	pldm_msgbuf_extract_p(buf, event_state);
 
 	pldm_msgbuf_extract_sensor_value(buf, *sensor_data_size,
 					 present_reading);
@@ -2172,8 +2172,8 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, sensor_id);
-	pldm_msgbuf_extract(buf, rearm_event_state);
+	pldm_msgbuf_extract_p(buf, sensor_id);
+	pldm_msgbuf_extract_p(buf, rearm_event_state);
 
 	return pldm_msgbuf_destroy(buf);
 }
@@ -2242,7 +2242,7 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, completion_code);
+	pldm_msgbuf_extract_p(buf, completion_code);
 
 	return pldm_msgbuf_destroy(buf);
 }
@@ -2272,10 +2272,10 @@
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, event_message_global_enable);
-	pldm_msgbuf_extract(buf, transport_protocol_type);
-	pldm_msgbuf_extract(buf, event_receiver_address_info);
-	pldm_msgbuf_extract(buf, heartbeat_timer);
+	pldm_msgbuf_extract_p(buf, event_message_global_enable);
+	pldm_msgbuf_extract_p(buf, transport_protocol_type);
+	pldm_msgbuf_extract_p(buf, event_receiver_address_info);
+	pldm_msgbuf_extract_p(buf, heartbeat_timer);
 
 	rc = pldm_msgbuf_destroy(buf);
 	if (rc) {
@@ -2386,7 +2386,7 @@
 		return rc;
 	}
 
-	rc = pldm_msgbuf_extract(buf, completion_code);
+	rc = pldm_msgbuf_extract_p(buf, completion_code);
 	if (rc) {
 		return rc;
 	}
@@ -2394,8 +2394,8 @@
 		return *completion_code;
 	}
 
-	pldm_msgbuf_extract(buf, tid);
-	rc = pldm_msgbuf_extract(buf, event_id);
+	pldm_msgbuf_extract_p(buf, tid);
+	rc = pldm_msgbuf_extract_p(buf, event_id);
 	if (rc) {
 		return rc;
 	}
@@ -2403,14 +2403,14 @@
 		return PLDM_SUCCESS;
 	}
 
-	pldm_msgbuf_extract(buf, next_data_transfer_handle);
-	rc = pldm_msgbuf_extract(buf, transfer_flag);
+	pldm_msgbuf_extract_p(buf, next_data_transfer_handle);
+	rc = pldm_msgbuf_extract_p(buf, transfer_flag);
 	if (rc) {
 		return rc;
 	}
 
-	pldm_msgbuf_extract(buf, event_class);
-	rc = pldm_msgbuf_extract(buf, event_data_size);
+	pldm_msgbuf_extract_p(buf, event_class);
+	rc = pldm_msgbuf_extract_p(buf, event_data_size);
 	if (rc) {
 		return rc;
 	}
@@ -2424,7 +2424,7 @@
 
 	if (*transfer_flag == PLDM_END ||
 	    *transfer_flag == PLDM_START_AND_END) {
-		pldm_msgbuf_extract(buf, event_data_integrity_checksum);
+		pldm_msgbuf_extract_p(buf, event_data_integrity_checksum);
 	}
 
 	return pldm_msgbuf_destroy_consumed(buf);
diff --git a/tests/msgbuf_generic.c b/tests/msgbuf_generic.c
index 3307917..9119273 100644
--- a/tests/msgbuf_generic.c
+++ b/tests/msgbuf_generic.c
@@ -35,7 +35,7 @@
 
     expect(pldm_msgbuf_init(ctx, sizeof(buf), buf, sizeof(buf)) ==
            PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctx, &val) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctx, val) == PLDM_SUCCESS);
     expect(val == 0xa5);
     expect(pldm_msgbuf_destroy(ctx) == PLDM_SUCCESS);
 }
@@ -49,7 +49,7 @@
 
     expect(pldm_msgbuf_init(ctx, sizeof(buf), buf, sizeof(buf)) ==
            PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctx, &val) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctx, val) == PLDM_SUCCESS);
     expect(val == -1);
     expect(pldm_msgbuf_destroy(ctx) == PLDM_SUCCESS);
 }
@@ -63,7 +63,7 @@
 
     expect(pldm_msgbuf_init(ctx, sizeof(buf), buf, sizeof(buf)) ==
            PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctx, &val) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctx, val) == PLDM_SUCCESS);
     expect(val == 0x5aa5);
     expect(pldm_msgbuf_destroy(ctx) == PLDM_SUCCESS);
 }
@@ -77,7 +77,7 @@
 
     expect(pldm_msgbuf_init(ctx, sizeof(buf), buf, sizeof(buf)) ==
            PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctx, &val) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctx, val) == PLDM_SUCCESS);
     expect(val == INT16_MIN);
     expect(pldm_msgbuf_destroy(ctx) == PLDM_SUCCESS);
 }
@@ -91,7 +91,7 @@
 
     expect(pldm_msgbuf_init(ctx, sizeof(buf), buf, sizeof(buf)) ==
            PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctx, &val) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctx, val) == PLDM_SUCCESS);
     expect(val == 0x5a00ffa5);
     expect(pldm_msgbuf_destroy(ctx) == PLDM_SUCCESS);
 }
@@ -105,7 +105,7 @@
 
     expect(pldm_msgbuf_init(ctx, sizeof(buf), buf, sizeof(buf)) ==
            PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctx, &val) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctx, val) == PLDM_SUCCESS);
     expect(val == INT32_MIN);
     expect(pldm_msgbuf_destroy(ctx) == PLDM_SUCCESS);
 }
@@ -125,7 +125,7 @@
 
     expect(pldm_msgbuf_init(ctx, sizeof(buf), buf, sizeof(buf)) ==
            PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctx, &val) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctx, val) == PLDM_SUCCESS);
     expect(val == FLT_MAX);
     expect(pldm_msgbuf_destroy(ctx) == PLDM_SUCCESS);
 }
@@ -159,7 +159,7 @@
     struct pldm_msgbuf* ctxExtract = &_ctxExtract;
 
     expect(pldm_msgbuf_init(ctxExtract, 0, buf, sizeof(buf)) == PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctxExtract, &checkVal) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctxExtract, checkVal) == PLDM_SUCCESS);
 
     expect(src == checkVal);
     expect(pldm_msgbuf_destroy(ctxExtract) == PLDM_SUCCESS);
@@ -181,7 +181,7 @@
     struct pldm_msgbuf* ctxExtract = &_ctxExtract;
 
     expect(pldm_msgbuf_init(ctxExtract, 0, buf, sizeof(buf)) == PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctxExtract, &checkVal) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctxExtract, checkVal) == PLDM_SUCCESS);
 
     expect(src == checkVal);
     expect(pldm_msgbuf_destroy(ctxExtract) == PLDM_SUCCESS);
@@ -203,7 +203,7 @@
     struct pldm_msgbuf* ctxExtract = &_ctxExtract;
 
     expect(pldm_msgbuf_init(ctxExtract, 0, buf, sizeof(buf)) == PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctxExtract, &checkVal) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctxExtract, checkVal) == PLDM_SUCCESS);
 
     expect(src == checkVal);
     expect(pldm_msgbuf_destroy(ctxExtract) == PLDM_SUCCESS);
@@ -225,7 +225,7 @@
     struct pldm_msgbuf* ctxExtract = &_ctxExtract;
 
     expect(pldm_msgbuf_init(ctxExtract, 0, buf, sizeof(buf)) == PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctxExtract, &checkVal) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctxExtract, checkVal) == PLDM_SUCCESS);
 
     expect(src == checkVal);
     expect(pldm_msgbuf_destroy(ctxExtract) == PLDM_SUCCESS);
@@ -247,7 +247,7 @@
     struct pldm_msgbuf* ctxExtract = &_ctxExtract;
 
     expect(pldm_msgbuf_init(ctxExtract, 0, buf, sizeof(buf)) == PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctxExtract, &checkVal) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctxExtract, checkVal) == PLDM_SUCCESS);
 
     expect(src == checkVal);
     expect(pldm_msgbuf_destroy(ctxExtract) == PLDM_SUCCESS);
@@ -269,7 +269,7 @@
     struct pldm_msgbuf* ctxExtract = &_ctxExtract;
 
     expect(pldm_msgbuf_init(ctxExtract, 0, buf, sizeof(buf)) == PLDM_SUCCESS);
-    expect(pldm_msgbuf_extract(ctxExtract, &checkVal) == PLDM_SUCCESS);
+    expect(pldm_msgbuf_extract(ctxExtract, checkVal) == PLDM_SUCCESS);
 
     expect(src == checkVal);
     expect(pldm_msgbuf_destroy(ctxExtract) == PLDM_SUCCESS);