blob: a0e1204ea611796a925651f8b661279da8778c9b [file] [log] [blame]
Patrick Williams691668f2023-11-01 08:19:10 -05001/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
Andrew Jefferyc63f63a2023-02-24 22:29:33 +10302#ifndef PLDM_MSGBUF_H
3#define PLDM_MSGBUF_H
4
Andrew Jeffery860a43d2024-08-23 01:21:58 +00005#include "compiler.h"
6
Andrew Jeffery66c77232024-04-24 11:42:02 +09307/*
8 * Historically, many of the structs exposed in libpldm's public headers are
9 * defined with __attribute__((packed)). This is unfortunate: it gives the
10 * impression that a wire-format buffer can be cast to the message type to make
11 * the message's fields easily accessible. As it turns out, that's not
12 * that's valid for several reasons:
13 *
14 * 1. Casting the wire-format buffer to a struct of the message type doesn't
15 * abstract the endianness of message field values
16 *
17 * 2. Some messages contain packed tagged union fields which cannot be properly
18 * described in a C struct.
19 *
20 * The msgbuf APIs exist to assist with (un)packing the wire-format in a way
21 * that is type-safe, spatially memory-safe, endian-safe, performant, and
22 * free of undefined-behaviour. Message structs that are added to the public
23 * library API should no-longer be marked __attribute__((packed)), and the
24 * implementation of their encode and decode functions must exploit the msgbuf
25 * API.
26 *
27 * However, we would like to allow implementation of codec functions in terms of
28 * msgbuf APIs even if they're decoding a message into a (historically) packed
29 * struct. Some of the complexity that follows is a consequence of the packed/
30 * unpacked conflict.
31 */
32
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103033#ifdef __cplusplus
Andrew Jeffery37dd6a32023-05-12 16:04:06 +093034/*
35 * Fix up C11's _Static_assert() vs C++'s static_assert().
36 *
37 * Can we please have nice things for once.
38 */
39// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
40#define _Static_assert(...) static_assert(__VA_ARGS__)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103041extern "C" {
42#endif
43
Andrew Jefferyb0c1d202023-11-07 22:08:44 +103044#include <libpldm/base.h>
45#include <libpldm/pldm_types.h>
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103046
Andrew Jeffery66c77232024-04-24 11:42:02 +093047#include "compiler.h"
48
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103049#include <assert.h>
50#include <endian.h>
Andrew Jefferyc8df31c2024-05-21 16:47:43 +093051#include <errno.h>
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103052#include <limits.h>
53#include <stdbool.h>
Andrew Jeffery66c77232024-04-24 11:42:02 +093054#include <stdint.h>
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103055#include <string.h>
56#include <sys/types.h>
Thu Nguyen15237782024-07-02 09:30:41 +000057#include <uchar.h>
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103058
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +093059/*
60 * We can't use static_assert() outside of some other C construct. Deal
61 * with high-level global assertions by burying them in an unused struct
62 * declaration, that has a sole member for compliance with the requirement that
63 * types must have a size.
64*/
65static struct {
66 static_assert(
67 INTMAX_MAX != SIZE_MAX,
68 "Extraction and insertion value comparisons may be broken");
69 static_assert(INTMAX_MIN + INTMAX_MAX <= 0,
70 "Extraction and insertion arithmetic may be broken");
71 int compliance;
Andrew Jeffery860a43d2024-08-23 01:21:58 +000072} build_assertions LIBPLDM_CC_UNUSED;
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +093073
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103074struct pldm_msgbuf {
Thu Nguyen062c8762023-04-22 20:45:04 +070075 uint8_t *cursor;
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +093076 intmax_t remaining;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +103077};
78
Andrew Jefferya1896962025-03-03 21:41:25 +103079LIBPLDM_CC_NONNULL
80LIBPLDM_CC_ALWAYS_INLINE
81// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
82void pldm__msgbuf_cleanup(struct pldm_msgbuf *ctx LIBPLDM_CC_UNUSED)
83{
84 assert(ctx->cursor == NULL && ctx->remaining == INTMAX_MIN);
85}
86
87#ifdef __cplusplus
88// NOLINTBEGIN(bugprone-macro-parentheses)
89#define PLDM_MSGBUF_DEFINE_P(name) \
90 struct pldm_msgbuf _##name LIBPLDM_CC_CLEANUP( \
91 pldm__msgbuf_cleanup) = { NULL, INTMAX_MIN }; \
92 auto *name = &(_##name)
93// NOLINTEND(bugprone-macro-parentheses)
94#else
95#define PLDM_MSGBUF_DEFINE_P(name) \
96 struct pldm_msgbuf _##name LIBPLDM_CC_CLEANUP( \
97 pldm__msgbuf_cleanup) = { NULL, INTMAX_MIN }; \
98 struct pldm_msgbuf *(name) = &(_##name)
99#endif
100
101LIBPLDM_CC_NONNULL
102LIBPLDM_CC_ALWAYS_INLINE
103// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
104int pldm__msgbuf_invalidate(struct pldm_msgbuf *ctx)
105{
106 ctx->remaining = INTMAX_MIN;
107 return -EOVERFLOW;
108}
109
Andrew Jefferyd861a682024-06-03 21:43:09 +0930110/**
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030111 * @brief Initialize pldm buf struct for buf extractor
112 *
113 * @param[out] ctx - pldm_msgbuf context for extractor
114 * @param[in] minsize - The minimum required length of buffer `buf`
115 * @param[in] buf - buffer to be extracted
116 * @param[in] len - size of buffer
117 *
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930118 * @return 0 on success, otherwise an error code appropriate for the current
119 * personality.
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030120 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300121LIBPLDM_CC_NONNULL
Andrew Jeffery704e4d52025-03-03 17:13:50 +1030122LIBPLDM_CC_ALWAYS_INLINE
123LIBPLDM_CC_WARN_UNUSED_RESULT
124int
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930125// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930126pldm_msgbuf_init_errno(struct pldm_msgbuf *ctx, size_t minsize, const void *buf,
127 size_t len)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030128{
Andrew Jefferya1896962025-03-03 21:41:25 +1030129 ctx->cursor = NULL;
130
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930131 if ((minsize > len)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030132 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030133 }
134
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930135#if INTMAX_MAX < SIZE_MAX
136 if (len > INTMAX_MAX) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030137 return pldm__msgbuf_invalidate(ctx);
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930138 }
139#endif
140
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930141 if (UINTPTR_MAX - (uintptr_t)buf < len) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030142 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030143 }
144
145 ctx->cursor = (uint8_t *)buf;
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930146 ctx->remaining = (intmax_t)len;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030147
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930148 return 0;
149}
150
151/**
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030152 * @brief Validate buffer overflow state
153 *
154 * @param[in] ctx - pldm_msgbuf context for extractor
155 *
156 * @return PLDM_SUCCESS if there are zero or more bytes of data that remain
157 * unread from the buffer. Otherwise, PLDM_ERROR_INVALID_LENGTH indicates that a
158 * prior accesses would have occurred beyond the bounds of the buffer, and
159 * PLDM_ERROR_INVALID_DATA indicates that the provided context was not a valid
160 * pointer.
161 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300162LIBPLDM_CC_NONNULL
Andrew Jeffery704e4d52025-03-03 17:13:50 +1030163LIBPLDM_CC_ALWAYS_INLINE
164LIBPLDM_CC_WARN_UNUSED_RESULT
165int pldm_msgbuf_validate(struct pldm_msgbuf *ctx)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030166{
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930167 if (ctx->remaining < 0) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930168 return -EOVERFLOW;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030169 }
170
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930171 return 0;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030172}
173
174/**
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930175 * @brief Test whether a message buffer has been exactly consumed
176 *
177 * @param[in] ctx - pldm_msgbuf context for extractor
178 *
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030179 * @return 0 iff there are zero bytes of data that remain unread from the buffer
Andrew Jeffery63b5a662025-03-05 13:26:12 +1030180 * and no overflow has occurred. Otherwise, -EBADMSG if the buffer has not been
181 * completely consumed, or -EOVERFLOW if accesses were attempted beyond the
182 * bounds of the buffer.
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930183 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300184LIBPLDM_CC_NONNULL
Andrew Jeffery704e4d52025-03-03 17:13:50 +1030185LIBPLDM_CC_ALWAYS_INLINE
186LIBPLDM_CC_WARN_UNUSED_RESULT
187int pldm_msgbuf_consumed(struct pldm_msgbuf *ctx)
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930188{
Andrew Jeffery63b5a662025-03-05 13:26:12 +1030189 if (ctx->remaining > 0) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930190 return -EBADMSG;
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930191 }
192
Andrew Jeffery63b5a662025-03-05 13:26:12 +1030193 if (ctx->remaining < 0) {
194 return -EOVERFLOW;
195 }
196
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930197 return 0;
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930198}
199
200/**
Andrew Jefferya1896962025-03-03 21:41:25 +1030201 * @brief End use of a msgbuf under error conditions
202 *
203 * @param[in] ctx - The msgbuf instance to discard
204 * @param[in] error - The error value to propagate
205 *
206 * Under normal conditions use of a msgbuf instance must be ended using @ref
207 * pldm_msgbuf_complete or one of its related APIs. Under error conditions, @ref
208 * pldm_msgbuf_discard should be used instead, as it makes it straight-forward
209 * to finalise the msgbuf while propagating the existing error code.
210 *
211 * @return The value provided in @param error
212 */
213LIBPLDM_CC_NONNULL
214LIBPLDM_CC_ALWAYS_INLINE
215LIBPLDM_CC_WARN_UNUSED_RESULT
216int pldm_msgbuf_discard(struct pldm_msgbuf *ctx, int error)
217{
218 ctx->cursor = NULL;
219 pldm__msgbuf_invalidate(ctx);
220 return error;
221}
222
223/**
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030224 * @brief Complete the pldm_msgbuf instance
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030225 *
226 * @param[in] ctx - pldm_msgbuf context for extractor
227 *
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030228 * @return 0 if all buffer accesses were in-bounds, -EOVERFLOW otherwise.
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030229 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300230LIBPLDM_CC_NONNULL
Andrew Jeffery704e4d52025-03-03 17:13:50 +1030231LIBPLDM_CC_ALWAYS_INLINE
232LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030233int pldm_msgbuf_complete(struct pldm_msgbuf *ctx)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030234{
Andrew Jefferya1896962025-03-03 21:41:25 +1030235 return pldm_msgbuf_discard(ctx, pldm_msgbuf_validate(ctx));
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030236}
237
238/**
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030239 * @brief Complete the pldm_msgbuf instance, and check that the underlying buffer
240 * has been entirely consumed without overflow
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930241 *
242 * @param[in] ctx - pldm_msgbuf context
243 *
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030244 * @return 0 if all buffer access were in-bounds and completely consume the
Andrew Jeffery63b5a662025-03-05 13:26:12 +1030245 * underlying buffer. Otherwise, -EBADMSG if the buffer has not been completely
246 * consumed, or -EOVERFLOW if accesses were attempted beyond the bounds of the
247 * buffer.
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930248 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300249LIBPLDM_CC_NONNULL
Andrew Jeffery704e4d52025-03-03 17:13:50 +1030250LIBPLDM_CC_ALWAYS_INLINE
251LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jeffery70d21c92025-03-05 12:59:42 +1030252int pldm_msgbuf_complete_consumed(struct pldm_msgbuf *ctx)
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930253{
Andrew Jefferya1896962025-03-03 21:41:25 +1030254 return pldm_msgbuf_discard(ctx, pldm_msgbuf_consumed(ctx));
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930255}
256
Andrew Jeffery66c77232024-04-24 11:42:02 +0930257/*
258 * Exploit the pre-processor to perform type checking by macro substitution.
259 *
260 * A C type is defined by its alignment as well as its object
261 * size, and compilers have a hammer to enforce it in the form of
262 * `-Waddress-of-packed-member`. Due to the unpacked/packed struct conflict in
263 * the libpldm public API this presents a problem: Naively attempting to use the
264 * msgbuf APIs on a member of a packed struct would yield an error.
265 *
266 * The msgbuf APIs are implemented such that data is moved through unaligned
267 * pointers in a safe way, but to mitigate `-Waddress-of-packed-member` we must
268 * make the object pointers take a trip through `void *` at its API boundary.
269 * That presents a bit too much of an opportunity to non-surgically remove your
270 * own foot, so here we set about doing something to mitigate that as well.
271 *
272 * pldm_msgbuf_extract_typecheck() exists to enforce pointer type correctness
273 * only for the purpose of object sizes, disregarding alignment. We have a few
274 * constraints that cause some headaches:
275 *
276 * 1. We have to perform the type-check before a call through a C function,
277 * as the function must take the object pointer argument as `void *`.
278 * Essentially, this constrains us to doing something with macros.
279 *
280 * 2. While libpldm is a C library, its test suite is written in C++ to take
281 * advantage of gtest.
282 *
283 * 3. Ideally we'd do something with C's `static_assert()`, however
284 * `static_assert()` is defined as void, and as we're constrained to macros,
285 * using `static_assert()` would require a statement-expression
286 *
287 * 4. Currently the project is built with `-std=c17`. CPP statement-expressions
288 * are a GNU extension. We prefer to avoid switching to `-std=gnu17` just for
289 * the purpose of enabling statement-expressions in this one instance.
290 *
291 * 5. We can achieve a conditional build error using `pldm_require_obj_type()`,
292 * however it's implemented in terms of `_Generic()`, which is not available
293 * in C++.
294 *
295 * Combined this means we need separate solutions for C and C++.
296 *
297 * For C, as we don't have statement-expressions, we need to exploit some other
298 * language feature to inject a `pldm_require_obj_type()` prior to the msgbuf
299 * API function call. We also have to take care of the fact that the call-sites
300 * may be in the context of a variable assignment for error-handling purposes.
301 * The key observation is that we can use the comma operator as a sequence point
302 * to order the type check before the API call, discarding the "result" value of
303 * the type check and yielding the return value of the API call.
304 *
305 * C++ could be less of a headache than the C as we can leverage template
306 * functions. An advantage of template functions is that while their definition
307 * is driven by instantion, the definition does not appear at the source
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +0530308 * location of the instantiation, which gives it a great leg-up over the problems
Andrew Jeffery66c77232024-04-24 11:42:02 +0930309 * we have in the C path. However, the use of the msgbuf APIs in the test suite
310 * still makes things somewhat tricky, as the call-sites in the test suite are
311 * wrapped up in EXPECT_*() gtest macros. Ideally we'd implement functions that
312 * takes both the object type and the required type as template arguments, and
313 * then define the object pointer parameter as `void *` for a call through to
314 * the appropriate msgbuf API. However, because the msgbuf API call-sites are
315 * encapsulated in gtest macros, use of commas in the template specification
316 * causes pre-processor confusion. In this way we're constrained to only one
317 * template argument per function.
318 *
319 * Implement the C++ path using template functions that take the destination
320 * object type as a template argument, while the name of the function symbols
321 * are derived from the required type. The manual implementations of these
322 * appear at the end of the header. The type safety is actually enforced
323 * by `static_assert()` this time, as we can use statements as we're not
324 * constrained to an expression in the templated function body.
325 *
326 * The invocations of pldm_msgbuf_extract_typecheck() typically result in
327 * double-evaluation of some arguments. We're not yet bothered by this for two
328 * reasons:
329 *
330 * 1. The nature of the current call-sites are such that there are no
331 * argument expressions that result in undesirable side-effects
332 *
333 * 2. It's an API internal to the libpldm implementation, and we can fix things
334 * whenever something crops up the violates the observation in 1.
335 */
336#ifdef __cplusplus
337#define pldm_msgbuf_extract_typecheck(ty, fn, dst, ...) \
338 pldm_msgbuf_typecheck_##ty<decltype(dst)>(__VA_ARGS__)
339#else
340#define pldm_msgbuf_extract_typecheck(ty, fn, dst, ...) \
341 (pldm_require_obj_type(dst, ty), fn(__VA_ARGS__))
342#endif
343
Andrew Jefferydb7b8322023-04-12 23:05:21 +0930344/**
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030345 * @brief pldm_msgbuf extractor for a uint8_t
346 *
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +0530347 * @param[in,out] ctx - pldm_msgbuf context for extractor
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030348 * @param[out] dst - destination of extracted value
349 *
350 * @return PLDM_SUCCESS if buffer accesses were in-bounds,
351 * PLDM_ERROR_INVALID_LENGTH otherwise.
352 * PLDM_ERROR_INVALID_DATA if input a invalid ctx
353 */
Andrew Jeffery66c77232024-04-24 11:42:02 +0930354#define pldm_msgbuf_extract_uint8(ctx, dst) \
355 pldm_msgbuf_extract_typecheck(uint8_t, pldm__msgbuf_extract_uint8, \
Andrew Jefferye5f12532024-10-01 12:18:49 +0930356 dst, ctx, (void *)&(dst))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300357LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300358LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery66c77232024-04-24 11:42:02 +0930359// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +0930360pldm__msgbuf_extract_uint8(struct pldm_msgbuf *ctx, void *dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030361{
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930362 if (ctx->remaining >= (intmax_t)sizeof(uint8_t)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030363 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930364 memcpy(dst, ctx->cursor, sizeof(uint8_t));
365 ctx->cursor++;
366 ctx->remaining -= sizeof(uint8_t);
367 return 0;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030368 }
369
Andrew Jefferya1896962025-03-03 21:41:25 +1030370 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(uint8_t)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930371 ctx->remaining -= sizeof(uint8_t);
Andrew Jefferya1896962025-03-03 21:41:25 +1030372 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930373 }
Andrew Jeffery66c77232024-04-24 11:42:02 +0930374
Andrew Jefferya1896962025-03-03 21:41:25 +1030375 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030376}
377
Andrew Jeffery66c77232024-04-24 11:42:02 +0930378#define pldm_msgbuf_extract_int8(ctx, dst) \
379 pldm_msgbuf_extract_typecheck(int8_t, pldm__msgbuf_extract_int8, dst, \
Andrew Jefferye5f12532024-10-01 12:18:49 +0930380 ctx, (void *)&(dst))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300381LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300382LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery66c77232024-04-24 11:42:02 +0930383// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +0930384pldm__msgbuf_extract_int8(struct pldm_msgbuf *ctx, void *dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030385{
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930386 if (ctx->remaining >= (intmax_t)sizeof(int8_t)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030387 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930388 memcpy(dst, ctx->cursor, sizeof(int8_t));
389 ctx->cursor++;
390 ctx->remaining -= sizeof(int8_t);
391 return 0;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030392 }
393
Andrew Jefferya1896962025-03-03 21:41:25 +1030394 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(int8_t)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930395 ctx->remaining -= sizeof(int8_t);
Andrew Jefferya1896962025-03-03 21:41:25 +1030396 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930397 }
398
Andrew Jefferya1896962025-03-03 21:41:25 +1030399 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030400}
401
Andrew Jeffery66c77232024-04-24 11:42:02 +0930402#define pldm_msgbuf_extract_uint16(ctx, dst) \
403 pldm_msgbuf_extract_typecheck(uint16_t, pldm__msgbuf_extract_uint16, \
Andrew Jefferye5f12532024-10-01 12:18:49 +0930404 dst, ctx, (void *)&(dst))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300405LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300406LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery66c77232024-04-24 11:42:02 +0930407// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +0930408pldm__msgbuf_extract_uint16(struct pldm_msgbuf *ctx, void *dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030409{
410 uint16_t ldst;
411
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930412 // Check for underflow while tracking the magnitude of the buffer overflow
413 static_assert(
414 // NOLINTNEXTLINE(bugprone-sizeof-expression)
415 sizeof(ldst) < INTMAX_MAX,
416 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930417
418 if (ctx->remaining >= (intmax_t)sizeof(ldst)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030419 assert(ctx->cursor);
420
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930421 // Use memcpy() to have the compiler deal with any alignment
422 // issues on the target architecture
423 memcpy(&ldst, ctx->cursor, sizeof(ldst));
424
425 // Only assign the target value once it's correctly decoded
426 ldst = le16toh(ldst);
427
428 // Allow storing to unaligned
429 memcpy(dst, &ldst, sizeof(ldst));
430
431 ctx->cursor += sizeof(ldst);
432 ctx->remaining -= sizeof(ldst);
433 return 0;
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930434 }
435
Andrew Jefferya1896962025-03-03 21:41:25 +1030436 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(ldst)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930437 ctx->remaining -= sizeof(ldst);
Andrew Jefferya1896962025-03-03 21:41:25 +1030438 return -EOVERFLOW;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030439 }
440
Andrew Jefferya1896962025-03-03 21:41:25 +1030441 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030442}
443
Andrew Jeffery66c77232024-04-24 11:42:02 +0930444#define pldm_msgbuf_extract_int16(ctx, dst) \
445 pldm_msgbuf_extract_typecheck(int16_t, pldm__msgbuf_extract_int16, \
Andrew Jefferye5f12532024-10-01 12:18:49 +0930446 dst, ctx, (void *)&(dst))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300447LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300448LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery66c77232024-04-24 11:42:02 +0930449// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +0930450pldm__msgbuf_extract_int16(struct pldm_msgbuf *ctx, void *dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030451{
452 int16_t ldst;
453
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930454 static_assert(
455 // NOLINTNEXTLINE(bugprone-sizeof-expression)
456 sizeof(ldst) < INTMAX_MAX,
457 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930458
459 if (ctx->remaining >= (intmax_t)sizeof(ldst)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030460 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930461 memcpy(&ldst, ctx->cursor, sizeof(ldst));
462 ldst = le16toh(ldst);
463 memcpy(dst, &ldst, sizeof(ldst));
464 ctx->cursor += sizeof(ldst);
465 ctx->remaining -= sizeof(ldst);
466 return 0;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030467 }
468
Andrew Jefferya1896962025-03-03 21:41:25 +1030469 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(ldst)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930470 ctx->remaining -= sizeof(ldst);
Andrew Jefferya1896962025-03-03 21:41:25 +1030471 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930472 }
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030473
Andrew Jefferya1896962025-03-03 21:41:25 +1030474 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030475}
476
Andrew Jeffery66c77232024-04-24 11:42:02 +0930477#define pldm_msgbuf_extract_uint32(ctx, dst) \
478 pldm_msgbuf_extract_typecheck(uint32_t, pldm__msgbuf_extract_uint32, \
Andrew Jefferye5f12532024-10-01 12:18:49 +0930479 dst, ctx, (void *)&(dst))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300480LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300481LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery66c77232024-04-24 11:42:02 +0930482// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +0930483pldm__msgbuf_extract_uint32(struct pldm_msgbuf *ctx, void *dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030484{
485 uint32_t ldst;
486
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930487 static_assert(
488 // NOLINTNEXTLINE(bugprone-sizeof-expression)
489 sizeof(ldst) < INTMAX_MAX,
490 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930491
492 if (ctx->remaining >= (intmax_t)sizeof(ldst)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030493 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930494 memcpy(&ldst, ctx->cursor, sizeof(ldst));
495 ldst = le32toh(ldst);
496 memcpy(dst, &ldst, sizeof(ldst));
497 ctx->cursor += sizeof(ldst);
498 ctx->remaining -= sizeof(ldst);
499 return 0;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030500 }
501
Andrew Jefferya1896962025-03-03 21:41:25 +1030502 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(ldst)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930503 ctx->remaining -= sizeof(ldst);
Andrew Jefferya1896962025-03-03 21:41:25 +1030504 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930505 }
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030506
Andrew Jefferya1896962025-03-03 21:41:25 +1030507 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030508}
509
Andrew Jeffery66c77232024-04-24 11:42:02 +0930510#define pldm_msgbuf_extract_int32(ctx, dst) \
511 pldm_msgbuf_extract_typecheck(int32_t, pldm__msgbuf_extract_int32, \
Andrew Jefferye5f12532024-10-01 12:18:49 +0930512 dst, ctx, (void *)&(dst))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300513LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300514LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery66c77232024-04-24 11:42:02 +0930515// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +0930516pldm__msgbuf_extract_int32(struct pldm_msgbuf *ctx, void *dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030517{
518 int32_t ldst;
519
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930520 static_assert(
521 // NOLINTNEXTLINE(bugprone-sizeof-expression)
522 sizeof(ldst) < INTMAX_MAX,
523 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930524
525 if (ctx->remaining >= (intmax_t)sizeof(ldst)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030526 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930527 memcpy(&ldst, ctx->cursor, sizeof(ldst));
528 ldst = le32toh(ldst);
529 memcpy(dst, &ldst, sizeof(ldst));
530 ctx->cursor += sizeof(ldst);
531 ctx->remaining -= sizeof(ldst);
532 return 0;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030533 }
534
Andrew Jefferya1896962025-03-03 21:41:25 +1030535 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(ldst)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930536 ctx->remaining -= sizeof(ldst);
Andrew Jefferya1896962025-03-03 21:41:25 +1030537 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930538 }
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030539
Andrew Jefferya1896962025-03-03 21:41:25 +1030540 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030541}
542
Andrew Jeffery66c77232024-04-24 11:42:02 +0930543#define pldm_msgbuf_extract_real32(ctx, dst) \
544 pldm_msgbuf_extract_typecheck(real32_t, pldm__msgbuf_extract_real32, \
Andrew Jefferye5f12532024-10-01 12:18:49 +0930545 dst, ctx, (void *)&(dst))
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300546LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300547LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery66c77232024-04-24 11:42:02 +0930548// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +0930549pldm__msgbuf_extract_real32(struct pldm_msgbuf *ctx, void *dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030550{
551 uint32_t ldst;
552
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930553 static_assert(sizeof(real32_t) == sizeof(ldst),
554 "Mismatched type sizes for dst and ldst");
Andrew Jeffery66c77232024-04-24 11:42:02 +0930555
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930556 static_assert(
557 // NOLINTNEXTLINE(bugprone-sizeof-expression)
558 sizeof(ldst) < INTMAX_MAX,
559 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930560
561 if (ctx->remaining >= (intmax_t)sizeof(ldst)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030562 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930563 memcpy(&ldst, ctx->cursor, sizeof(ldst));
564 ldst = le32toh(ldst);
565 memcpy(dst, &ldst, sizeof(ldst));
566 ctx->cursor += sizeof(ldst);
567 ctx->remaining -= sizeof(ldst);
568 return 0;
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030569 }
570
Andrew Jefferya1896962025-03-03 21:41:25 +1030571 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(ldst)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930572 ctx->remaining -= sizeof(ldst);
Andrew Jefferya1896962025-03-03 21:41:25 +1030573 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930574 }
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030575
Andrew Jefferya1896962025-03-03 21:41:25 +1030576 return pldm__msgbuf_invalidate(ctx);
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030577}
578
Andrew Jeffery66c77232024-04-24 11:42:02 +0930579/**
580 * Extract the field at the msgbuf cursor into the lvalue named by dst.
581 *
582 * @param ctx The msgbuf context object
583 * @param dst The lvalue into which the field at the msgbuf cursor should be
584 * extracted
585 *
586 * @return PLDM_SUCCESS on success, otherwise another value on error
587 */
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030588#define pldm_msgbuf_extract(ctx, dst) \
Andrew Jeffery66c77232024-04-24 11:42:02 +0930589 _Generic((dst), \
590 uint8_t: pldm__msgbuf_extract_uint8, \
591 int8_t: pldm__msgbuf_extract_int8, \
592 uint16_t: pldm__msgbuf_extract_uint16, \
593 int16_t: pldm__msgbuf_extract_int16, \
594 uint32_t: pldm__msgbuf_extract_uint32, \
595 int32_t: pldm__msgbuf_extract_int32, \
596 real32_t: pldm__msgbuf_extract_real32)(ctx, (void *)&(dst))
597
598/**
599 * Extract the field at the msgbuf cursor into the object pointed-to by dst.
600 *
601 * @param ctx The msgbuf context object
602 * @param dst The pointer to the object into which the field at the msgbuf
603 * cursor should be extracted
604 *
605 * @return PLDM_SUCCESS on success, otherwise another value on error
606 */
607#define pldm_msgbuf_extract_p(ctx, dst) \
608 _Generic((dst), \
609 uint8_t *: pldm__msgbuf_extract_uint8, \
610 int8_t *: pldm__msgbuf_extract_int8, \
611 uint16_t *: pldm__msgbuf_extract_uint16, \
612 int16_t *: pldm__msgbuf_extract_int16, \
613 uint32_t *: pldm__msgbuf_extract_uint32, \
614 int32_t *: pldm__msgbuf_extract_int32, \
615 real32_t *: pldm__msgbuf_extract_real32)(ctx, dst)
Andrew Jefferyc63f63a2023-02-24 22:29:33 +1030616
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000617/**
618 * @ref pldm_msgbuf_extract_array
619 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300620LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000621LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300622LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery1c571442024-07-08 10:25:48 +0930623// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000624pldm__msgbuf_extract_array_void(struct pldm_msgbuf *ctx, size_t count,
625 void *dst, size_t dst_count)
Andrew Jeffery369b1212023-04-20 15:44:48 +0930626{
Andrew Jefferya1896962025-03-03 21:41:25 +1030627 if (count > dst_count) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930628 return -EINVAL;
Andrew Jeffery369b1212023-04-20 15:44:48 +0930629 }
630
631 if (!count) {
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930632 return 0;
Andrew Jeffery369b1212023-04-20 15:44:48 +0930633 }
634
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930635#if INTMAX_MAX < SIZE_MAX
636 if (count > INTMAX_MAX) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030637 return pldm__msgbuf_invalidate(ctx);
Andrew Jeffery369b1212023-04-20 15:44:48 +0930638 }
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930639#endif
Andrew Jeffery369b1212023-04-20 15:44:48 +0930640
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930641 if (ctx->remaining >= (intmax_t)count) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030642 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930643 memcpy(dst, ctx->cursor, count);
644 ctx->cursor += count;
645 ctx->remaining -= (intmax_t)count;
646 return 0;
Andrew Jeffery369b1212023-04-20 15:44:48 +0930647 }
648
Andrew Jefferya1896962025-03-03 21:41:25 +1030649 if (ctx->remaining > INTMAX_MIN + (intmax_t)count) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930650 ctx->remaining -= (intmax_t)count;
Andrew Jefferya1896962025-03-03 21:41:25 +1030651 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930652 }
Andrew Jeffery369b1212023-04-20 15:44:48 +0930653
Andrew Jefferya1896962025-03-03 21:41:25 +1030654 return pldm__msgbuf_invalidate(ctx);
Andrew Jeffery369b1212023-04-20 15:44:48 +0930655}
656
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000657/**
658 * @ref pldm_msgbuf_extract_array
659 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300660LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000661LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300662LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000663pldm_msgbuf_extract_array_char(struct pldm_msgbuf *ctx, size_t count, char *dst,
664 size_t dst_count)
Andrew Jeffery1c571442024-07-08 10:25:48 +0930665{
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000666 return pldm__msgbuf_extract_array_void(ctx, count, dst, dst_count);
Andrew Jeffery1c571442024-07-08 10:25:48 +0930667}
668
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000669/**
670 * @ref pldm_msgbuf_extract_array
671 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300672LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000673LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300674LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000675pldm_msgbuf_extract_array_uint8(struct pldm_msgbuf *ctx, size_t count,
676 uint8_t *dst, size_t dst_count)
Andrew Jeffery1c571442024-07-08 10:25:48 +0930677{
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000678 return pldm__msgbuf_extract_array_void(ctx, count, dst, dst_count);
Andrew Jeffery1c571442024-07-08 10:25:48 +0930679}
680
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000681/**
682 * Extract an array of data from the msgbuf instance
683 *
684 * @param ctx - The msgbuf instance from which to extract an array of data
685 * @param count - The number of array elements to extract
686 * @param dst - The array object into which elements from @p ctx should be
687 extracted
688 * @param dst_count - The maximum number of elements to place into @p dst
689 *
690 * Note that both @p count and @p dst_count can only be counted by `sizeof` for
691 * arrays where `sizeof(*dst) == 1` holds. Specifically, they count the number
692 * of array elements and _not_ the object size of the array.
693 */
694#define pldm_msgbuf_extract_array(ctx, count, dst, dst_count) \
Andrew Jeffery1c571442024-07-08 10:25:48 +0930695 _Generic((*(dst)), \
696 uint8_t: pldm_msgbuf_extract_array_uint8, \
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000697 char: pldm_msgbuf_extract_array_char)(ctx, count, dst, \
698 dst_count)
Andrew Jeffery369b1212023-04-20 15:44:48 +0930699
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300700LIBPLDM_CC_NONNULL
Matt Johnstone8d8d332024-10-28 17:13:32 +0800701LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_insert_uint64(struct pldm_msgbuf *ctx,
702 const uint64_t src)
703{
704 uint64_t val = htole64(src);
705
Matt Johnstone8d8d332024-10-28 17:13:32 +0800706 static_assert(
707 // NOLINTNEXTLINE(bugprone-sizeof-expression)
708 sizeof(src) < INTMAX_MAX,
709 "The following addition may not uphold the runtime assertion");
710
711 if (ctx->remaining >= (intmax_t)sizeof(src)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030712 assert(ctx->cursor);
Matt Johnstone8d8d332024-10-28 17:13:32 +0800713 memcpy(ctx->cursor, &val, sizeof(val));
714 ctx->cursor += sizeof(src);
715 ctx->remaining -= sizeof(src);
716 return 0;
717 }
718
Andrew Jefferya1896962025-03-03 21:41:25 +1030719 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(src)) {
Matt Johnstone8d8d332024-10-28 17:13:32 +0800720 ctx->remaining -= sizeof(src);
Andrew Jefferya1896962025-03-03 21:41:25 +1030721 return -EOVERFLOW;
Matt Johnstone8d8d332024-10-28 17:13:32 +0800722 }
723
Andrew Jefferya1896962025-03-03 21:41:25 +1030724 return pldm__msgbuf_invalidate(ctx);
Matt Johnstone8d8d332024-10-28 17:13:32 +0800725}
726
727LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300728LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_insert_uint32(struct pldm_msgbuf *ctx,
729 const uint32_t src)
Thu Nguyen062c8762023-04-22 20:45:04 +0700730{
731 uint32_t val = htole32(src);
732
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930733 static_assert(
734 // NOLINTNEXTLINE(bugprone-sizeof-expression)
735 sizeof(src) < INTMAX_MAX,
736 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930737
738 if (ctx->remaining >= (intmax_t)sizeof(src)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030739 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930740 memcpy(ctx->cursor, &val, sizeof(val));
741 ctx->cursor += sizeof(src);
742 ctx->remaining -= sizeof(src);
743 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700744 }
745
Andrew Jefferya1896962025-03-03 21:41:25 +1030746 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(src)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930747 ctx->remaining -= sizeof(src);
Andrew Jefferya1896962025-03-03 21:41:25 +1030748 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930749 }
Thu Nguyen062c8762023-04-22 20:45:04 +0700750
Andrew Jefferya1896962025-03-03 21:41:25 +1030751 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700752}
753
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300754LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300755LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_insert_uint16(struct pldm_msgbuf *ctx,
756 const uint16_t src)
Thu Nguyen062c8762023-04-22 20:45:04 +0700757{
758 uint16_t val = htole16(src);
759
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930760 static_assert(
761 // NOLINTNEXTLINE(bugprone-sizeof-expression)
762 sizeof(src) < INTMAX_MAX,
763 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930764
765 if (ctx->remaining >= (intmax_t)sizeof(src)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030766 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930767 memcpy(ctx->cursor, &val, sizeof(val));
768 ctx->cursor += sizeof(src);
769 ctx->remaining -= sizeof(src);
770 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700771 }
772
Andrew Jefferya1896962025-03-03 21:41:25 +1030773 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(src)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930774 ctx->remaining -= sizeof(src);
Andrew Jefferya1896962025-03-03 21:41:25 +1030775 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930776 }
Thu Nguyen062c8762023-04-22 20:45:04 +0700777
Andrew Jefferya1896962025-03-03 21:41:25 +1030778 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700779}
780
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300781LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300782LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_insert_uint8(struct pldm_msgbuf *ctx,
783 const uint8_t src)
Thu Nguyen062c8762023-04-22 20:45:04 +0700784{
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930785 static_assert(
786 // NOLINTNEXTLINE(bugprone-sizeof-expression)
787 sizeof(src) < INTMAX_MAX,
788 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930789
790 if (ctx->remaining >= (intmax_t)sizeof(src)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030791 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930792 memcpy(ctx->cursor, &src, sizeof(src));
793 ctx->cursor += sizeof(src);
794 ctx->remaining -= sizeof(src);
795 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700796 }
797
Andrew Jefferya1896962025-03-03 21:41:25 +1030798 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(src)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930799 ctx->remaining -= sizeof(src);
Andrew Jefferya1896962025-03-03 21:41:25 +1030800 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930801 }
Thu Nguyen062c8762023-04-22 20:45:04 +0700802
Andrew Jefferya1896962025-03-03 21:41:25 +1030803 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700804}
805
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300806LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300807LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_insert_int32(struct pldm_msgbuf *ctx,
808 const int32_t src)
Thu Nguyen062c8762023-04-22 20:45:04 +0700809{
810 int32_t val = htole32(src);
811
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930812 static_assert(
813 // NOLINTNEXTLINE(bugprone-sizeof-expression)
814 sizeof(src) < INTMAX_MAX,
815 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930816
817 if (ctx->remaining >= (intmax_t)sizeof(src)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030818 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930819 memcpy(ctx->cursor, &val, sizeof(val));
820 ctx->cursor += sizeof(src);
821 ctx->remaining -= sizeof(src);
822 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700823 }
824
Andrew Jefferya1896962025-03-03 21:41:25 +1030825 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(src)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930826 ctx->remaining -= sizeof(src);
Andrew Jefferya1896962025-03-03 21:41:25 +1030827 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930828 }
Thu Nguyen062c8762023-04-22 20:45:04 +0700829
Andrew Jefferya1896962025-03-03 21:41:25 +1030830 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700831}
832
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300833LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300834LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_insert_int16(struct pldm_msgbuf *ctx,
835 const int16_t src)
Thu Nguyen062c8762023-04-22 20:45:04 +0700836{
837 int16_t val = htole16(src);
838
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930839 static_assert(
840 // NOLINTNEXTLINE(bugprone-sizeof-expression)
841 sizeof(src) < INTMAX_MAX,
842 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930843
844 if (ctx->remaining >= (intmax_t)sizeof(src)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030845 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930846 memcpy(ctx->cursor, &val, sizeof(val));
847 ctx->cursor += sizeof(src);
848 ctx->remaining -= sizeof(src);
849 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700850 }
851
Andrew Jefferya1896962025-03-03 21:41:25 +1030852 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(src)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930853 ctx->remaining -= sizeof(src);
Andrew Jefferya1896962025-03-03 21:41:25 +1030854 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930855 }
Thu Nguyen062c8762023-04-22 20:45:04 +0700856
Andrew Jefferya1896962025-03-03 21:41:25 +1030857 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700858}
859
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300860LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300861LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_insert_int8(struct pldm_msgbuf *ctx,
862 const int8_t src)
Thu Nguyen062c8762023-04-22 20:45:04 +0700863{
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930864 static_assert(
865 // NOLINTNEXTLINE(bugprone-sizeof-expression)
866 sizeof(src) < INTMAX_MAX,
867 "The following addition may not uphold the runtime assertion");
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930868
869 if (ctx->remaining >= (intmax_t)sizeof(src)) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030870 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930871 memcpy(ctx->cursor, &src, sizeof(src));
872 ctx->cursor += sizeof(src);
873 ctx->remaining -= sizeof(src);
874 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700875 }
876
Andrew Jefferya1896962025-03-03 21:41:25 +1030877 if (ctx->remaining > INTMAX_MIN + (intmax_t)sizeof(src)) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930878 ctx->remaining -= sizeof(src);
Andrew Jefferya1896962025-03-03 21:41:25 +1030879 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930880 }
Thu Nguyen062c8762023-04-22 20:45:04 +0700881
Andrew Jefferya1896962025-03-03 21:41:25 +1030882 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700883}
884
885#define pldm_msgbuf_insert(dst, src) \
Andrew Jeffery37dd6a32023-05-12 16:04:06 +0930886 _Generic((src), \
887 uint8_t: pldm_msgbuf_insert_uint8, \
888 int8_t: pldm_msgbuf_insert_int8, \
889 uint16_t: pldm_msgbuf_insert_uint16, \
890 int16_t: pldm_msgbuf_insert_int16, \
891 uint32_t: pldm_msgbuf_insert_uint32, \
Matt Johnstone8d8d332024-10-28 17:13:32 +0800892 int32_t: pldm_msgbuf_insert_int32, \
893 uint64_t: pldm_msgbuf_insert_uint64)(dst, src)
Thu Nguyen062c8762023-04-22 20:45:04 +0700894
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000895/**
896 * @ref pldm_msgbuf_insert_array
897 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300898LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000899LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300900LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery1c571442024-07-08 10:25:48 +0930901// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000902pldm__msgbuf_insert_array_void(struct pldm_msgbuf *ctx, size_t count,
903 const void *src, size_t src_count)
Thu Nguyen062c8762023-04-22 20:45:04 +0700904{
Andrew Jefferya1896962025-03-03 21:41:25 +1030905 if (count > src_count) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +0930906 return -EINVAL;
Thu Nguyen062c8762023-04-22 20:45:04 +0700907 }
908
909 if (!count) {
Andrew Jefferyc8df31c2024-05-21 16:47:43 +0930910 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700911 }
912
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930913#if INTMAX_MAX < SIZE_MAX
914 if (count > INTMAX_MAX) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030915 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700916 }
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930917#endif
Thu Nguyen062c8762023-04-22 20:45:04 +0700918
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930919 if (ctx->remaining >= (intmax_t)count) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030920 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930921 memcpy(ctx->cursor, src, count);
922 ctx->cursor += count;
923 ctx->remaining -= (intmax_t)count;
924 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700925 }
926
Andrew Jefferya1896962025-03-03 21:41:25 +1030927 if (ctx->remaining > INTMAX_MIN + (intmax_t)count) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930928 ctx->remaining -= (intmax_t)count;
Andrew Jefferya1896962025-03-03 21:41:25 +1030929 return -EOVERFLOW;
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930930 }
Thu Nguyen062c8762023-04-22 20:45:04 +0700931
Andrew Jefferya1896962025-03-03 21:41:25 +1030932 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700933}
934
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000935/**
936 * @ref pldm_msgbuf_insert_array
937 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300938LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000939LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300940LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000941pldm_msgbuf_insert_array_char(struct pldm_msgbuf *ctx, size_t count,
942 const char *src, size_t src_count)
Andrew Jeffery1c571442024-07-08 10:25:48 +0930943{
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000944 return pldm__msgbuf_insert_array_void(ctx, count, src, src_count);
Andrew Jeffery1c571442024-07-08 10:25:48 +0930945}
946
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000947/**
948 * @ref pldm_msgbuf_insert_array
949 */
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +0300950LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000951LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300952LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000953pldm_msgbuf_insert_array_uint8(struct pldm_msgbuf *ctx, size_t count,
954 const uint8_t *src, size_t src_count)
Andrew Jeffery1c571442024-07-08 10:25:48 +0930955{
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000956 return pldm__msgbuf_insert_array_void(ctx, count, src, src_count);
Andrew Jeffery1c571442024-07-08 10:25:48 +0930957}
958
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000959/**
960 * Insert an array of data into the msgbuf instance
961 *
962 * @param ctx - The msgbuf instance into which the array of data should be
963 * inserted
964 * @param count - The number of array elements to insert
965 * @param src - The array object from which elements should be inserted into
966 @p ctx
967 * @param src_count - The maximum number of elements to insert from @p src
968 *
969 * Note that both @p count and @p src_count can only be counted by `sizeof` for
970 * arrays where `sizeof(*dst) == 1` holds. Specifically, they count the number
971 * of array elements and _not_ the object size of the array.
972 */
973#define pldm_msgbuf_insert_array(dst, count, src, src_count) \
Andrew Jeffery1c571442024-07-08 10:25:48 +0930974 _Generic((*(src)), \
975 uint8_t: pldm_msgbuf_insert_array_uint8, \
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +0000976 char: pldm_msgbuf_insert_array_char)(dst, count, src, \
977 src_count)
Thu Nguyen062c8762023-04-22 20:45:04 +0700978
Varsha Kaverappa79393822024-08-07 00:40:13 -0500979LIBPLDM_CC_NONNULL_ARGS(1)
Andrew Jefferycb569bc2024-09-01 09:38:09 +0300980LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_span_required(struct pldm_msgbuf *ctx,
981 size_t required,
982 void **cursor)
Thu Nguyen062c8762023-04-22 20:45:04 +0700983{
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930984#if INTMAX_MAX < SIZE_MAX
985 if (required > INTMAX_MAX) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030986 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +0700987 }
Andrew Jeffery2ff8cf82024-05-17 15:20:46 +0930988#endif
Thu Nguyen062c8762023-04-22 20:45:04 +0700989
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930990 if (ctx->remaining >= (intmax_t)required) {
Andrew Jefferya1896962025-03-03 21:41:25 +1030991 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +0930992 if (cursor) {
993 *cursor = ctx->cursor;
994 }
995 ctx->cursor += required;
996 ctx->remaining -= (intmax_t)required;
997 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +0700998 }
999
Andrew Jefferya1896962025-03-03 21:41:25 +10301000 if (ctx->remaining > INTMAX_MIN + (intmax_t)required) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301001 ctx->remaining -= (intmax_t)required;
Andrew Jefferya1896962025-03-03 21:41:25 +10301002 return -EOVERFLOW;
Varsha Kaverappa79393822024-08-07 00:40:13 -05001003 }
Thu Nguyen062c8762023-04-22 20:45:04 +07001004
Andrew Jefferya1896962025-03-03 21:41:25 +10301005 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen062c8762023-04-22 20:45:04 +07001006}
1007
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +03001008LIBPLDM_CC_NONNULL_ARGS(1)
Andrew Jefferycb569bc2024-09-01 09:38:09 +03001009LIBPLDM_CC_ALWAYS_INLINE int
Thu Nguyen9c83d682024-07-02 08:43:09 +00001010pldm_msgbuf_span_string_ascii(struct pldm_msgbuf *ctx, void **cursor,
1011 size_t *length)
1012{
1013 intmax_t measured;
1014
Thu Nguyen9c83d682024-07-02 08:43:09 +00001015 if (ctx->remaining < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301016 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen9c83d682024-07-02 08:43:09 +00001017 }
Andrew Jefferya1896962025-03-03 21:41:25 +10301018 assert(ctx->cursor);
Thu Nguyen9c83d682024-07-02 08:43:09 +00001019
1020 measured = (intmax_t)strnlen((const char *)ctx->cursor, ctx->remaining);
1021 if (measured == ctx->remaining) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301022 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen9c83d682024-07-02 08:43:09 +00001023 }
1024
1025 /* Include the NUL terminator in the span length, as spans are opaque */
1026 measured++;
1027
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301028 if (ctx->remaining >= measured) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301029 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301030 if (cursor) {
1031 *cursor = ctx->cursor;
1032 }
1033
1034 ctx->cursor += measured;
1035
1036 if (length) {
1037 *length = measured;
1038 }
1039
1040 ctx->remaining -= measured;
1041 return 0;
Thu Nguyen9c83d682024-07-02 08:43:09 +00001042 }
1043
Andrew Jefferya1896962025-03-03 21:41:25 +10301044 if (ctx->remaining > INTMAX_MIN + measured) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301045 ctx->remaining -= measured;
Andrew Jefferya1896962025-03-03 21:41:25 +10301046 return -EOVERFLOW;
Thu Nguyen9c83d682024-07-02 08:43:09 +00001047 }
1048
Andrew Jefferya1896962025-03-03 21:41:25 +10301049 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen9c83d682024-07-02 08:43:09 +00001050}
1051
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +03001052LIBPLDM_CC_NONNULL_ARGS(1)
Andrew Jefferycb569bc2024-09-01 09:38:09 +03001053LIBPLDM_CC_ALWAYS_INLINE int
Thu Nguyen15237782024-07-02 09:30:41 +00001054pldm_msgbuf_span_string_utf16(struct pldm_msgbuf *ctx, void **cursor,
1055 size_t *length)
1056{
1057 static const char16_t term = 0;
1058 ptrdiff_t measured;
1059 void *end;
1060
Thu Nguyen15237782024-07-02 09:30:41 +00001061 if (ctx->remaining < 0) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301062 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen15237782024-07-02 09:30:41 +00001063 }
Andrew Jefferya1896962025-03-03 21:41:25 +10301064 assert(ctx->cursor);
Thu Nguyen15237782024-07-02 09:30:41 +00001065
1066 /*
1067 * Avoid tripping up on UTF16-LE: We may have consecutive NUL _bytes_ that do
1068 * not form a UTF16 NUL _code-point_ due to alignment with respect to the
1069 * start of the string
1070 */
Andrew Jeffery2b440d42024-07-25 10:36:08 +09301071 end = ctx->cursor;
Thu Nguyen15237782024-07-02 09:30:41 +00001072 do {
1073 if (end != ctx->cursor) {
1074 /*
1075 * If we've looped we've found a relatively-unaligned NUL code-point.
1076 * Scan again from a relatively-aligned start point.
1077 */
1078 end = (char *)end + 1;
1079 }
1080 measured = (char *)end - (char *)ctx->cursor;
Andrew Jeffery2b440d42024-07-25 10:36:08 +09301081 end = memmem(end, ctx->remaining - measured, &term,
1082 sizeof(term));
Thu Nguyen15237782024-07-02 09:30:41 +00001083 } while (end && ((uintptr_t)end & 1) != ((uintptr_t)ctx->cursor & 1));
1084
1085 if (!end) {
1086 /*
1087 * Optimistically, the last required pattern byte was one beyond the end of
1088 * the buffer. Setting ctx->remaining negative ensures the
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301089 * `pldm_msgbuf_complete*()` APIs also return an error.
Thu Nguyen15237782024-07-02 09:30:41 +00001090 */
Andrew Jefferya1896962025-03-03 21:41:25 +10301091 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen15237782024-07-02 09:30:41 +00001092 }
1093
1094 end = (char *)end + sizeof(char16_t);
1095 measured = (char *)end - (char *)ctx->cursor;
1096
1097#if INTMAX_MAX < PTRDIFF_MAX
1098 if (measured >= INTMAX_MAX) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301099 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen15237782024-07-02 09:30:41 +00001100 }
1101#endif
1102
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301103 if (ctx->remaining >= (intmax_t)measured) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301104 assert(ctx->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301105 if (cursor) {
1106 *cursor = ctx->cursor;
1107 }
1108
1109 ctx->cursor += measured;
1110
1111 if (length) {
1112 *length = (size_t)measured;
1113 }
1114
1115 ctx->remaining -= (intmax_t)measured;
1116 return 0;
Thu Nguyen15237782024-07-02 09:30:41 +00001117 }
1118
Andrew Jefferya1896962025-03-03 21:41:25 +10301119 if (ctx->remaining > INTMAX_MIN + (intmax_t)measured) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301120 ctx->remaining -= (intmax_t)measured;
Andrew Jefferya1896962025-03-03 21:41:25 +10301121 return -EOVERFLOW;
Thu Nguyen15237782024-07-02 09:30:41 +00001122 }
1123
Andrew Jefferya1896962025-03-03 21:41:25 +10301124 return pldm__msgbuf_invalidate(ctx);
Thu Nguyen15237782024-07-02 09:30:41 +00001125}
1126
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +03001127LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +03001128LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery76712f62024-05-22 15:19:00 +09301129pldm_msgbuf_span_remaining(struct pldm_msgbuf *ctx, void **cursor, size_t *len)
Thu Nguyen062c8762023-04-22 20:45:04 +07001130{
Thu Nguyen062c8762023-04-22 20:45:04 +07001131 if (ctx->remaining < 0) {
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301132 return -EOVERFLOW;
Thu Nguyen062c8762023-04-22 20:45:04 +07001133 }
1134
Andrew Jefferya1896962025-03-03 21:41:25 +10301135 assert(ctx->cursor);
Thu Nguyen062c8762023-04-22 20:45:04 +07001136 *cursor = ctx->cursor;
1137 ctx->cursor += ctx->remaining;
1138 *len = ctx->remaining;
1139 ctx->remaining = 0;
1140
Andrew Jefferyc8df31c2024-05-21 16:47:43 +09301141 return 0;
Thu Nguyen062c8762023-04-22 20:45:04 +07001142}
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001143
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001144LIBPLDM_CC_NONNULL
1145LIBPLDM_CC_ALWAYS_INLINE int
1146pldm_msgbuf_peek_remaining(struct pldm_msgbuf *ctx, void **cursor, size_t *len)
1147{
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001148 if (ctx->remaining < 0) {
1149 return -EOVERFLOW;
1150 }
1151
Andrew Jefferya1896962025-03-03 21:41:25 +10301152 assert(ctx->cursor);
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001153 *cursor = ctx->cursor;
1154 *len = ctx->remaining;
1155
1156 return 0;
1157}
1158
1159LIBPLDM_CC_NONNULL
1160LIBPLDM_CC_ALWAYS_INLINE int pldm_msgbuf_skip(struct pldm_msgbuf *ctx,
1161 size_t count)
1162{
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001163#if INTMAX_MAX < SIZE_MAX
1164 if (count > INTMAX_MAX) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301165 return pldm__msgbuf_invalidate(ctx);
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001166 }
1167#endif
1168
Andrew Jeffery7e68f342025-03-03 21:37:23 +10301169 if (ctx->remaining >= (intmax_t)count) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301170 assert(ctx->cursor);
Andrew Jeffery7e68f342025-03-03 21:37:23 +10301171 ctx->cursor += count;
1172 ctx->remaining -= (intmax_t)count;
1173 return 0;
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001174 }
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001175
Andrew Jefferya1896962025-03-03 21:41:25 +10301176 if (ctx->remaining > INTMAX_MIN + (intmax_t)count) {
Andrew Jeffery7e68f342025-03-03 21:37:23 +10301177 ctx->remaining -= (intmax_t)count;
Andrew Jefferya1896962025-03-03 21:41:25 +10301178 return -EOVERFLOW;
Andrew Jeffery7e68f342025-03-03 21:37:23 +10301179 }
1180
Andrew Jefferya1896962025-03-03 21:41:25 +10301181 return pldm__msgbuf_invalidate(ctx);
Matt Johnston8f3b13c2024-10-16 16:08:21 +08001182}
1183
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001184/**
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301185 * @brief Complete the pldm_msgbuf instance and return the number of bytes
1186 * consumed.
Matt Johnston5d4f7b52024-12-12 14:03:57 +08001187 *
1188 * @param ctx - The msgbuf.
1189 * @param orig_len - The original size of the msgbuf, the `len` argument passed to
1190 * pldm_msgbuf_init_errno().
1191 * @param ret_used_len - The number of bytes that have been used from the msgbuf instance.
1192 *
1193 * This can be called after a number of pldm_msgbuf_insert...() calls to
1194 * determine the total size that was written.
1195 *
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301196 * @return 0 on success, -EOVERFLOW if an implausible orig_len was provided or
1197 * an out-of-bounds access occurred.
Matt Johnston5d4f7b52024-12-12 14:03:57 +08001198 */
1199LIBPLDM_CC_NONNULL
Andrew Jeffery704e4d52025-03-03 17:13:50 +10301200LIBPLDM_CC_ALWAYS_INLINE
1201LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jeffery70d21c92025-03-05 12:59:42 +10301202int pldm_msgbuf_complete_used(struct pldm_msgbuf *ctx, size_t orig_len,
1203 size_t *ret_used_len)
Matt Johnston5d4f7b52024-12-12 14:03:57 +08001204{
1205 int rc;
Andrew Jeffery704e4d52025-03-03 17:13:50 +10301206
Andrew Jefferya1896962025-03-03 21:41:25 +10301207 ctx->cursor = NULL;
Matt Johnston5d4f7b52024-12-12 14:03:57 +08001208 rc = pldm_msgbuf_validate(ctx);
1209 if (rc) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301210 pldm__msgbuf_invalidate(ctx);
Matt Johnston5d4f7b52024-12-12 14:03:57 +08001211 return rc;
1212 }
1213
1214 if ((size_t)ctx->remaining > orig_len) {
1215 /* Caller passed incorrect orig_len */
Andrew Jefferya1896962025-03-03 21:41:25 +10301216 return pldm__msgbuf_invalidate(ctx);
Matt Johnston5d4f7b52024-12-12 14:03:57 +08001217 }
1218
1219 *ret_used_len = orig_len - ctx->remaining;
Andrew Jefferya1896962025-03-03 21:41:25 +10301220 pldm__msgbuf_invalidate(ctx);
Matt Johnston5d4f7b52024-12-12 14:03:57 +08001221 return 0;
1222}
1223
1224/**
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001225 * @brief pldm_msgbuf copy data between two msg buffers
1226 *
Manojkiran Eda9e3a5d42024-06-17 16:06:42 +05301227 * @param[in,out] src - pldm_msgbuf for source from where value should be copied
1228 * @param[in,out] dst - destination of copy from source
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001229 * @param[in] size - size of data to be copied
1230 * @param[in] description - description of data copied
1231 *
1232 * @return PLDM_SUCCESS if buffer accesses were in-bounds,
1233 * PLDM_ERROR_INVALID_LENGTH otherwise.
1234 * PLDM_ERROR_INVALID_DATA if input is invalid
1235 */
1236#define pldm_msgbuf_copy(dst, src, type, name) \
1237 pldm__msgbuf_copy(dst, src, sizeof(type), #name)
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +03001238LIBPLDM_CC_NONNULL
Andrew Jefferycb569bc2024-09-01 09:38:09 +03001239LIBPLDM_CC_ALWAYS_INLINE int
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001240// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
Andrew Jeffery76712f62024-05-22 15:19:00 +09301241pldm__msgbuf_copy(struct pldm_msgbuf *dst, struct pldm_msgbuf *src, size_t size,
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +03001242 const char *description LIBPLDM_CC_UNUSED)
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001243{
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001244#if INTMAX_MAX < SIZE_MAX
1245 if (size > INTMAX_MAX) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301246 pldm__msgbuf_invalidate(src);
1247 pldm__msgbuf_invalidate(dst);
Andrew Jeffery830c1eb2024-10-04 10:48:10 +09301248 return -EOVERFLOW;
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001249 }
1250#endif
1251
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301252 if (src->remaining >= (intmax_t)size &&
1253 dst->remaining >= (intmax_t)size) {
Andrew Jefferya1896962025-03-03 21:41:25 +10301254 assert(src->cursor && dst->cursor);
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301255 memcpy(dst->cursor, src->cursor, size);
1256 src->cursor += size;
1257 src->remaining -= (intmax_t)size;
1258 dst->cursor += size;
1259 dst->remaining -= (intmax_t)size;
1260 return 0;
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001261 }
1262
Andrew Jefferya1896962025-03-03 21:41:25 +10301263 if (src->remaining > INTMAX_MIN + (intmax_t)size) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301264 src->remaining -= (intmax_t)size;
Andrew Jefferya1896962025-03-03 21:41:25 +10301265 } else {
1266 pldm__msgbuf_invalidate(src);
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001267 }
1268
Andrew Jefferya1896962025-03-03 21:41:25 +10301269 if (dst->remaining > INTMAX_MIN + (intmax_t)size) {
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301270 dst->remaining -= (intmax_t)size;
Andrew Jefferya1896962025-03-03 21:41:25 +10301271 } else {
1272 pldm__msgbuf_invalidate(dst);
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001273 }
1274
Andrew Jeffery4f60fb72024-09-23 13:56:44 +09301275 return -EOVERFLOW;
Varsha Kaverappa909bf7c2024-05-03 06:18:42 -05001276}
Andrew Jefferyc8df31c2024-05-21 16:47:43 +09301277
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +03001278LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001279LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +03001280LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery8b879602024-07-08 12:50:19 +09301281pldm_msgbuf_copy_string_ascii(struct pldm_msgbuf *dst, struct pldm_msgbuf *src)
1282{
1283 void *ascii = NULL;
1284 size_t len = 0;
1285 int rc;
1286
1287 rc = pldm_msgbuf_span_string_ascii(src, &ascii, &len);
1288 if (rc < 0) {
1289 return rc;
1290 }
1291
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001292 return pldm__msgbuf_insert_array_void(dst, len, ascii, len);
Andrew Jeffery8b879602024-07-08 12:50:19 +09301293}
1294
Andrew Jeffery90bbe6c2024-09-01 13:02:02 +03001295LIBPLDM_CC_NONNULL
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001296LIBPLDM_CC_WARN_UNUSED_RESULT
Andrew Jefferycb569bc2024-09-01 09:38:09 +03001297LIBPLDM_CC_ALWAYS_INLINE int
Andrew Jeffery56f73f92024-07-08 12:50:28 +09301298pldm_msgbuf_copy_string_utf16(struct pldm_msgbuf *dst, struct pldm_msgbuf *src)
1299{
1300 void *utf16 = NULL;
1301 size_t len = 0;
1302 int rc;
1303
1304 rc = pldm_msgbuf_span_string_utf16(src, &utf16, &len);
1305 if (rc < 0) {
1306 return rc;
1307 }
1308
Andrew Jeffery0a1be3c2024-08-11 08:34:10 +00001309 return pldm__msgbuf_insert_array_void(dst, len, utf16, len);
Andrew Jeffery56f73f92024-07-08 12:50:28 +09301310}
1311
Chau Ly1a4eed92025-03-21 14:57:57 +00001312/**
1313 * @brief pldm_msgbuf uint8_t extractor for a size_t
1314 *
1315 * @param[in,out] ctx - pldm_msgbuf context for extractor
1316 * @param[out] dst - destination of extracted value
1317 *
1318 * @return 0 if buffer accesses were in-bounds,
1319 * -EINVAL if dst pointer is invalid,
1320 * -EOVERFLOW is the buffer was out of bound.
1321 */
1322#define pldm_msgbuf_extract_uint8_to_size(ctx, dst) \
1323 pldm__msgbuf_extract_uint8_to_size(ctx, &(dst))
1324LIBPLDM_CC_NONNULL
1325LIBPLDM_CC_ALWAYS_INLINE int
1326// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
1327pldm__msgbuf_extract_uint8_to_size(struct pldm_msgbuf *ctx, size_t *dst)
1328{
1329 uint8_t value;
1330 int rc;
1331
1332 rc = pldm__msgbuf_extract_uint8(ctx, &value);
1333 if (rc) {
1334 return rc;
1335 }
1336
1337 static_assert(SIZE_MAX >= UINT8_MAX, "Invalid promotion");
1338
1339 *dst = value;
1340 return 0;
1341}
1342
1343/**
1344 * @brief pldm_msgbuf uint16_t extractor for a size_t
1345 *
1346 * @param[in,out] ctx - pldm_msgbuf context for extractor
1347 * @param[out] dst - destination of extracted value
1348 *
1349 * @return 0 if buffer accesses were in-bounds,
1350 * -EINVAL if dst pointer is invalid,
1351 * -EOVERFLOW is the buffer was out of bound.
1352 */
1353#define pldm_msgbuf_extract_uint16_to_size(ctx, dst) \
1354 pldm__msgbuf_extract_uint16_to_size(ctx, &(dst))
1355LIBPLDM_CC_NONNULL
1356LIBPLDM_CC_ALWAYS_INLINE int
1357// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
1358pldm__msgbuf_extract_uint16_to_size(struct pldm_msgbuf *ctx, size_t *dst)
1359{
1360 uint16_t value;
1361 int rc;
1362
1363 rc = pldm__msgbuf_extract_uint16(ctx, &value);
1364 if (rc) {
1365 return rc;
1366 }
1367
1368 static_assert(SIZE_MAX >= UINT16_MAX, "Invalid promotion");
1369
1370 *dst = value;
1371 return 0;
1372}
1373
1374/**
1375 * @brief pldm_msgbuf uint32_t extractor for a size_t
1376 *
1377 * @param[in,out] ctx - pldm_msgbuf context for extractor
1378 * @param[out] dst - destination of extracted value
1379 *
1380 * @return 0 if buffer accesses were in-bounds,
1381 * -EINVAL if dst pointer is invalid,
1382 * -EOVERFLOW is the buffer was out of bound.
1383 */
1384#define pldm_msgbuf_extract_uint32_to_size(ctx, dst) \
1385 pldm__msgbuf_extract_uint32_to_size(ctx, &(dst))
1386LIBPLDM_CC_NONNULL
1387LIBPLDM_CC_ALWAYS_INLINE int
1388// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
1389pldm__msgbuf_extract_uint32_to_size(struct pldm_msgbuf *ctx, size_t *dst)
1390{
1391 uint32_t value;
1392 int rc;
1393
1394 rc = pldm__msgbuf_extract_uint32(ctx, &value);
1395 if (rc) {
1396 return rc;
1397 }
1398
1399 static_assert(SIZE_MAX >= UINT32_MAX, "Invalid promotion");
1400
1401 *dst = value;
1402 return 0;
1403}
1404
Andrew Jefferyc63f63a2023-02-24 22:29:33 +10301405#ifdef __cplusplus
1406}
1407#endif
1408
Andrew Jeffery66c77232024-04-24 11:42:02 +09301409#ifdef __cplusplus
1410#include <type_traits>
1411
1412template <typename T>
1413static inline int pldm_msgbuf_typecheck_uint8_t(struct pldm_msgbuf *ctx,
1414 void *buf)
1415{
Andrew Jefferye5f12532024-10-01 12:18:49 +09301416 static_assert(std::is_same<uint8_t, T>::value);
Andrew Jeffery66c77232024-04-24 11:42:02 +09301417 return pldm__msgbuf_extract_uint8(ctx, buf);
1418}
1419
1420template <typename T>
1421static inline int pldm_msgbuf_typecheck_int8_t(struct pldm_msgbuf *ctx,
1422 void *buf)
1423{
Andrew Jefferye5f12532024-10-01 12:18:49 +09301424 static_assert(std::is_same<int8_t, T>::value);
Andrew Jeffery66c77232024-04-24 11:42:02 +09301425 return pldm__msgbuf_extract_int8(ctx, buf);
1426}
1427
1428template <typename T>
1429static inline int pldm_msgbuf_typecheck_uint16_t(struct pldm_msgbuf *ctx,
1430 void *buf)
1431{
Andrew Jefferye5f12532024-10-01 12:18:49 +09301432 static_assert(std::is_same<uint16_t, T>::value);
Andrew Jeffery66c77232024-04-24 11:42:02 +09301433 return pldm__msgbuf_extract_uint16(ctx, buf);
1434}
1435
1436template <typename T>
1437static inline int pldm_msgbuf_typecheck_int16_t(struct pldm_msgbuf *ctx,
1438 void *buf)
1439{
Andrew Jefferye5f12532024-10-01 12:18:49 +09301440 static_assert(std::is_same<int16_t, T>::value);
Andrew Jeffery66c77232024-04-24 11:42:02 +09301441 return pldm__msgbuf_extract_int16(ctx, buf);
1442}
1443
1444template <typename T>
1445static inline int pldm_msgbuf_typecheck_uint32_t(struct pldm_msgbuf *ctx,
1446 void *buf)
1447{
Andrew Jefferye5f12532024-10-01 12:18:49 +09301448 static_assert(std::is_same<uint32_t, T>::value);
Andrew Jeffery66c77232024-04-24 11:42:02 +09301449 return pldm__msgbuf_extract_uint32(ctx, buf);
1450}
1451
1452template <typename T>
1453static inline int pldm_msgbuf_typecheck_int32_t(struct pldm_msgbuf *ctx,
1454 void *buf)
1455{
Andrew Jefferye5f12532024-10-01 12:18:49 +09301456 static_assert(std::is_same<int32_t, T>::value);
Andrew Jeffery66c77232024-04-24 11:42:02 +09301457 return pldm__msgbuf_extract_int32(ctx, buf);
1458}
1459
1460template <typename T>
1461static inline int pldm_msgbuf_typecheck_real32_t(struct pldm_msgbuf *ctx,
1462 void *buf)
1463{
Andrew Jefferye5f12532024-10-01 12:18:49 +09301464 static_assert(std::is_same<real32_t, T>::value);
Andrew Jeffery66c77232024-04-24 11:42:02 +09301465 return pldm__msgbuf_extract_real32(ctx, buf);
1466}
1467#endif
1468
Andrew Jefferyc63f63a2023-02-24 22:29:33 +10301469#endif /* BUF_H */