msgbuf: Remove use of ssize_t for overflow tracking
There are a few concerns with the use of ssize_t in this context:
1. It's defined by POSIX and not C, and I'd prefer we not require POSIX
concepts where we can avoid it
2. ssize_t is defined over [-1, SSIZE_MAX] - it is not defined to have
the range of a regular signed type.
The source of both these statements is The Open Group Base
Specifications Issue 7, 2018 edition. IEEE Std 1003.1-2017 (Revision of
IEEE Std 1003.1-2008)
The second point directly contradicts how I was trying to use ssize_t in
the msgbuf implementation. As a result, switch the type of `remaining`
to intmax_t. Usually intmax_t is a problem child, but it's not used in
any public API, and it has the semantics I wanted by contrast to the
definition of ssize_t.
Note that we add assert() calls where we know the value of remaining
must be negative. Without the addition of the `assert()` calls in the
underflow checks, clang-analyzer gets tripped up by not being able to
prove `INTMAX_MIN + (intmax_t)sizeof(uint16_t) < 0`:
```
../src/platform.c:17:18: error: The left operand of '+' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult,-warnings-as-errors]
17 | if (ctx->length + sizeof(*ctx) < lower) {
| ^
../src/platform.c:2445:6: note: 'rc' is 0
2445 | if (rc) {
| ^~
../src/platform.c:2445:2: note: Taking false branch
2445 | if (rc) {
| ^
../src/platform.c:2449:7: note: Calling 'pldm_msgbuf_extract_value_pdr_hdr'
2449 | rc = pldm_msgbuf_extract_value_pdr_hdr(buf, &hdr);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/msgbuf/platform.h:17:2: note: Calling 'pldm__msgbuf_extract_uint16'
17 | pldm_msgbuf_extract(ctx, hdr->length);
| ^
../src/msgbuf/../msgbuf.h:517:2: note: expanded from macro 'pldm_msgbuf_extract'
517 | _Generic((dst), \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518 | uint8_t: pldm__msgbuf_extract_uint8, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
519 | int8_t: pldm__msgbuf_extract_int8, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
520 | uint16_t: pldm__msgbuf_extract_uint16, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
521 | int16_t: pldm__msgbuf_extract_int16, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
522 | uint32_t: pldm__msgbuf_extract_uint32, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
523 | int32_t: pldm__msgbuf_extract_int32, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
524 | real32_t: pldm__msgbuf_extract_real32)(ctx, (void *)&(dst))
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/msgbuf/../msgbuf.h:341:7: note: 'ctx' is non-null
341 | if (!ctx || !ctx->cursor || !dst) {
| ^~~
../src/msgbuf/../msgbuf.h:341:6: note: Left side of '||' is false
341 | if (!ctx || !ctx->cursor || !dst) {
| ^
../src/msgbuf/../msgbuf.h:341:20: note: Field 'cursor' is non-null
341 | if (!ctx || !ctx->cursor || !dst) {
| ^
../src/msgbuf/../msgbuf.h:341:6: note: Left side of '||' is false
341 | if (!ctx || !ctx->cursor || !dst) {
| ^
../src/msgbuf/../msgbuf.h:341:31: note: 'dst' is non-null
341 | if (!ctx || !ctx->cursor || !dst) {
| ^~~
../src/msgbuf/../msgbuf.h:341:2: note: Taking false branch
341 | if (!ctx || !ctx->cursor || !dst) {
| ^
../src/msgbuf/../msgbuf.h:347:2: note: Taking true branch
347 | if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(ldst)) {
| ^
../src/msgbuf/../msgbuf.h:348:3: note: Returning without writing to '*dst'
348 | return PLDM_ERROR_INVALID_LENGTH;
| ^
../src/msgbuf/platform.h:17:2: note: Returning from 'pldm__msgbuf_extract_uint16'
17 | pldm_msgbuf_extract(ctx, hdr->length);
| ^
../src/msgbuf/../msgbuf.h:517:2: note: expanded from macro 'pldm_msgbuf_extract'
517 | _Generic((dst), \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518 | uint8_t: pldm__msgbuf_extract_uint8, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
519 | int8_t: pldm__msgbuf_extract_int8, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
520 | uint16_t: pldm__msgbuf_extract_uint16, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
521 | int16_t: pldm__msgbuf_extract_int16, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
522 | uint32_t: pldm__msgbuf_extract_uint32, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
523 | int32_t: pldm__msgbuf_extract_int32, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
524 | real32_t: pldm__msgbuf_extract_real32)(ctx, (void *)&(dst))
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/msgbuf/platform.h:19:2: note: Returning without writing to 'hdr->length'
19 | return pldm_msgbuf_validate(ctx);
| ^
../src/platform.c:2449:7: note: Returning from 'pldm_msgbuf_extract_value_pdr_hdr'
2449 | rc = pldm_msgbuf_extract_value_pdr_hdr(buf, &hdr);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/platform.c:2450:6: note: 'rc' is 0
2450 | if (rc) {
| ^~
../src/platform.c:2450:2: note: Taking false branch
2450 | if (rc) {
| ^
../src/platform.c:2454:7: note: Calling 'pldm_platform_pdr_hdr_validate'
2454 | rc = pldm_platform_pdr_hdr_validate(
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2455 | &hdr, PLDM_PDR_NUMERIC_EFFECTER_PDR_MIN_LENGTH,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2456 | pdr_data_length);
| ~~~~~~~~~~~~~~~~
../src/platform.c:17:18: note: The left operand of '+' is a garbage value
17 | if (ctx->length + sizeof(*ctx) < lower) {
| ~~~~~~~~~~~ ^
```
Change-Id: Idbe5a14455ad677a39c8f535eddd9c2ce471c783
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
diff --git a/src/msgbuf.h b/src/msgbuf.h
index 691d9a6..f81eb13 100644
--- a/src/msgbuf.h
+++ b/src/msgbuf.h
@@ -52,9 +52,24 @@
#include <string.h>
#include <sys/types.h>
+/*
+ * We can't use static_assert() outside of some other C construct. Deal
+ * with high-level global assertions by burying them in an unused struct
+ * declaration, that has a sole member for compliance with the requirement that
+ * types must have a size.
+*/
+static struct {
+ static_assert(
+ INTMAX_MAX != SIZE_MAX,
+ "Extraction and insertion value comparisons may be broken");
+ static_assert(INTMAX_MIN + INTMAX_MAX <= 0,
+ "Extraction and insertion arithmetic may be broken");
+ int compliance;
+} build_assertions __attribute__((unused));
+
struct pldm_msgbuf {
uint8_t *cursor;
- ssize_t remaining;
+ intmax_t remaining;
};
/**
@@ -76,16 +91,22 @@
return PLDM_ERROR_INVALID_DATA;
}
- if ((minsize > len) || (len > SSIZE_MAX)) {
+ if ((minsize > len)) {
return PLDM_ERROR_INVALID_LENGTH;
}
+#if INTMAX_MAX < SIZE_MAX
+ if (len > INTMAX_MAX) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+#endif
+
if ((uintptr_t)buf + len < len) {
return PLDM_ERROR_INVALID_LENGTH;
}
ctx->cursor = (uint8_t *)buf;
- ctx->remaining = (ssize_t)len;
+ ctx->remaining = (intmax_t)len;
return PLDM_SUCCESS;
}
@@ -290,6 +311,10 @@
return PLDM_ERROR_INVALID_DATA;
}
+ if (ctx->remaining == INTMAX_MIN) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(uint8_t);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -312,6 +337,10 @@
return PLDM_ERROR_INVALID_DATA;
}
+ if (ctx->remaining == INTMAX_MIN) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(int8_t);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -336,6 +365,16 @@
return PLDM_ERROR_INVALID_DATA;
}
+ // Check for underflow while tracking the magnitude of the buffer overflow
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(ldst) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(ldst)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
// Check for buffer overflow. If we overflow, account for the request as
// negative values in ctx->remaining. This way we can debug how far
// we've overflowed.
@@ -376,6 +415,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(ldst) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(ldst)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(ldst);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -404,6 +451,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(ldst) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(ldst)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(ldst);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -431,6 +486,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(ldst) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(ldst)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(ldst);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -462,6 +525,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(ldst) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(ldst)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(ldst);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -525,11 +596,16 @@
return PLDM_SUCCESS;
}
- if (count >= SSIZE_MAX) {
+#if INTMAX_MAX < SIZE_MAX
+ if (count > INTMAX_MAX) {
return PLDM_ERROR_INVALID_LENGTH;
}
+#endif
- ctx->remaining -= (ssize_t)count;
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)count) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+ ctx->remaining -= (intmax_t)count;
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
return PLDM_ERROR_INVALID_LENGTH;
@@ -554,6 +630,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(src) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(src)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(src);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -575,6 +659,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(src) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(src)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(src);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -594,6 +686,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(src) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(src)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(src);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -615,6 +715,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(src) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(src)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(src);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -636,6 +744,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(src) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(src)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(src);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -655,6 +771,14 @@
return PLDM_ERROR_INVALID_DATA;
}
+ static_assert(
+ // NOLINTNEXTLINE(bugprone-sizeof-expression)
+ sizeof(src) < INTMAX_MAX,
+ "The following addition may not uphold the runtime assertion");
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)sizeof(src)) {
+ assert(ctx->remaining < 0);
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
ctx->remaining -= sizeof(src);
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
@@ -688,11 +812,16 @@
return PLDM_SUCCESS;
}
- if (count >= SSIZE_MAX) {
+#if INTMAX_MAX < SIZE_MAX
+ if (count > INTMAX_MAX) {
return PLDM_ERROR_INVALID_LENGTH;
}
+#endif
- ctx->remaining -= (ssize_t)count;
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)count) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+ ctx->remaining -= (intmax_t)count;
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
return PLDM_ERROR_INVALID_LENGTH;
@@ -715,11 +844,16 @@
return PLDM_ERROR_INVALID_DATA;
}
- if (required > SSIZE_MAX) {
+#if INTMAX_MAX < SIZE_MAX
+ if (required > INTMAX_MAX) {
return PLDM_ERROR_INVALID_LENGTH;
}
+#endif
- ctx->remaining -= (ssize_t)required;
+ if (ctx->remaining < INTMAX_MIN + (intmax_t)required) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+ ctx->remaining -= (intmax_t)required;
assert(ctx->remaining >= 0);
if (ctx->remaining < 0) {
return PLDM_ERROR_INVALID_LENGTH;
diff --git a/tests/msgbuf.cpp b/tests/msgbuf.cpp
index 15b0265..fecf514 100644
--- a/tests/msgbuf.cpp
+++ b/tests/msgbuf.cpp
@@ -143,6 +143,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+TEST(msgbuf, extract_under_uint8)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint8_t buf[1] = {};
+ uint8_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN;
+ EXPECT_NE(pldm_msgbuf_extract_uint8(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, extract_one_int8)
{
struct pldm_msgbuf _ctx;
@@ -169,6 +183,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+TEST(msgbuf, extract_under_int8)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint8_t buf[1] = {};
+ int8_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN;
+ EXPECT_NE(pldm_msgbuf_extract_int8(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, extract_one_uint16)
{
struct pldm_msgbuf _ctx;
@@ -183,6 +211,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_SUCCESS);
}
+TEST(msgbuf, extract_under_uint16)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint16_t buf[1] = {};
+ uint16_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_extract_uint16(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, extract_over_uint16)
{
struct pldm_msgbuf _ctx;
@@ -221,6 +263,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+TEST(msgbuf, extract_under_int16)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ int16_t buf[1] = {};
+ int16_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_extract_int16(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, extract_one_uint32)
{
struct pldm_msgbuf _ctx;
@@ -247,6 +303,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+TEST(msgbuf, extract_under_uint32)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint32_t buf[1] = {};
+ uint32_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_extract_uint32(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, extract_one_int32)
{
struct pldm_msgbuf _ctx;
@@ -273,6 +343,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+TEST(msgbuf, extract_under_int32)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ int32_t buf[1] = {};
+ int32_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_extract_int32(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, extract_one_real32)
{
struct pldm_msgbuf _ctx;
@@ -305,6 +389,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+TEST(msgbuf, extract_under_real32)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ real32_t buf[1] = {};
+ real32_t val;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_extract_real32(ctx, &val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, extract_array_uint8_buf0_req0)
{
struct pldm_msgbuf _ctx;
@@ -344,6 +442,19 @@
ASSERT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
}
+TEST(msgbuf, extract_under_array_uint8)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+ uint8_t buf[1] = {};
+ uint8_t arr[1];
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN;
+ EXPECT_NE(pldm_msgbuf_extract_array_uint8(ctx, arr, 1), PLDM_SUCCESS);
+ ASSERT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, consumed_under)
{
struct pldm_msgbuf _ctx;
@@ -410,6 +521,20 @@
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+TEST(msgbuf, insert_under_int32)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ int32_t buf[1] = {};
+ int32_t val = 0;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_insert_int32(ctx, val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_insert_uint32_good)
{
struct pldm_msgbuf _ctx;
@@ -441,6 +566,20 @@
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+TEST(msgbuf, insert_under_uint32)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint32_t buf[1] = {};
+ uint32_t val = 0;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_insert_uint32(ctx, val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_insert_uint16_good)
{
struct pldm_msgbuf _ctx;
@@ -472,6 +611,20 @@
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+TEST(msgbuf, insert_under_uint16)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint16_t buf[1] = {};
+ uint16_t val = 0;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_insert_uint16(ctx, val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_insert_int16_good)
{
struct pldm_msgbuf _ctx;
@@ -503,6 +656,20 @@
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+TEST(msgbuf, insert_under_int16)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ int16_t buf[1] = {};
+ int16_t val = 0;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_insert_int16(ctx, val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_insert_uint8_good)
{
struct pldm_msgbuf _ctx;
@@ -534,6 +701,20 @@
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+TEST(msgbuf, insert_under_uint8)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint8_t buf[1] = {};
+ uint8_t val = 0;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_insert_uint8(ctx, val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_insert_int8_good)
{
struct pldm_msgbuf _ctx;
@@ -565,6 +746,20 @@
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+TEST(msgbuf, insert_under_int8)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ int8_t buf[1] = {};
+ int8_t val = 0;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_insert_int8(ctx, val), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_insert_array_uint8_good)
{
struct pldm_msgbuf _ctx;
@@ -605,6 +800,21 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_SUCCESS);
}
+TEST(msgbuf, insert_under_array_uint8)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint8_t buf[1] = {};
+ uint8_t val[1] = {0};
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN + sizeof(val) - 1;
+ EXPECT_NE(pldm_msgbuf_insert_array_uint8(ctx, val, sizeof(val)),
+ PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_span_required_good)
{
struct pldm_msgbuf _ctx;
@@ -661,6 +871,20 @@
EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_SUCCESS);
}
+TEST(msgbuf, span_required_under)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+
+ uint8_t buf[1] = {};
+ void* cursor = nullptr;
+
+ ASSERT_EQ(pldm_msgbuf_init(ctx, 0, buf, 0), PLDM_SUCCESS);
+ ctx->remaining = INTMAX_MIN;
+ EXPECT_NE(pldm_msgbuf_span_required(ctx, 1, &cursor), PLDM_SUCCESS);
+ EXPECT_EQ(pldm_msgbuf_destroy(ctx), PLDM_ERROR_INVALID_LENGTH);
+}
+
TEST(msgbuf, pldm_msgbuf_span_remaining_good)
{
struct pldm_msgbuf _ctx;