dsp: base: Fix MultipartReceive Request decoding
This fix is based on DSP0240 v1.2.0 section 9.6.6 - Flag usage for
MultipartReceive (paragraph 351) and Table 17 MultipartReceive request
format.
- Removed RequestedSectionOffset check.
The Property can be 0 for any TransferOperation flag.
- Changed DataTransferHandle check.
The property can be 0 except with PLDM_XFER_NEXT_PART. Eg. In DSP0242
v1.0.0 section 9.8.2, Table 19, and DSP0240 v1.2.0 section 9.6.5, Table
17, when using MultipartReceive to read a file, the client has to send
transfer handle 0 with XFER_FIRST_PART.
Change-Id: I06428556f9dee341de97f72b015ed0347adc9454
Fixes: 9c76679224cf ("libpldm: Migrate to subproject")
Signed-off-by: Kasun Athukorala <kasunath@google.com>
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9f28c0d..b28a4fc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -96,6 +96,10 @@
- include, tests: Address concerns from -Wsign-compare
- dsp: base: decode_pldm_base_negotiate_transfer_params_resp() is stable
+- base:
+ - Removed RequestedSectionOffset check in decode_multipart_receive_req()
+ - Updated DataTransferHandle check in decode_multipart_receive_req()
+
### Security
## [0.14.0] 2025-08-11
diff --git a/src/dsp/base.c b/src/dsp/base.c
index cc805df..cd4878c 100644
--- a/src/dsp/base.c
+++ b/src/dsp/base.c
@@ -569,13 +569,14 @@
return PLDM_ERROR_UNEXPECTED_TRANSFER_FLAG_OPERATION;
}
- // A section offset of 0 is only valid on FIRST_PART or COMPLETE Xfers.
- if (*section_offset == 0 && (*transfer_opflag != PLDM_XFER_FIRST_PART &&
- *transfer_opflag != PLDM_XFER_COMPLETE)) {
- return PLDM_ERROR_INVALID_DATA;
- }
-
- if (*transfer_handle == 0 && *transfer_opflag != PLDM_XFER_COMPLETE) {
+ // By DSP0240 v1.2.0, section 9.6.5, Table 17, transfer handle can be 0 only
+ // if the transfer flag is one of XFER_FIRST_PART, XFER_COMPLETE or
+ // XFER_ABORT. In addition, it must be allowed in PLDM_XFER_CURRENT_PART as
+ // this may be used to retry the first part, in which case the transfer handle
+ // must again be 0. Therefore, the only operation for which it cannot be 0 is
+ // PLDM_XFER_NEXT_PART.
+ if ((*transfer_handle == 0) &&
+ (*transfer_opflag == PLDM_XFER_NEXT_PART)) {
return PLDM_ERROR_INVALID_DATA;
}
diff --git a/tests/dsp/base.cpp b/tests/dsp/base.cpp
index f146e7c..b2e9294 100644
--- a/tests/dsp/base.cpp
+++ b/tests/dsp/base.cpp
@@ -674,43 +674,6 @@
PLDM_ERROR_UNEXPECTED_TRANSFER_FLAG_OPERATION);
}
-TEST(DecodeMultipartReceiveRequest, testDecodeRequestFailBadOffset)
-{
- constexpr uint8_t kPldmType = PLDM_BASE;
- constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
- constexpr uint32_t kTransferCtx = 0x01;
- constexpr uint32_t kTransferHandle = 0x01;
- constexpr uint32_t kSectionOffset = 0x0;
-
- PLDM_MSG_DEFINE_P(msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
- PLDM_MSGBUF_RW_DEFINE_P(buf);
- int rc;
-
- // Header values don't matter for this test.
- rc = pldm_msgbuf_init_errno(buf, PLDM_MULTIPART_RECEIVE_REQ_BYTES,
- msg->payload, PLDM_MULTIPART_RECEIVE_REQ_BYTES);
- ASSERT_EQ(rc, 0);
- pldm_msgbuf_insert_uint8(buf, kPldmType);
- pldm_msgbuf_insert_uint8(buf, kFlag);
- pldm_msgbuf_insert_uint32(buf, kTransferCtx);
- pldm_msgbuf_insert_uint32(buf, kTransferHandle);
- pldm_msgbuf_insert_uint32(buf, kSectionOffset);
- rc = pldm_msgbuf_complete(buf);
- ASSERT_EQ(rc, 0);
-
- uint8_t pldm_type;
- uint8_t flag;
- uint32_t transfer_ctx;
- uint32_t transfer_handle;
- uint32_t section_offset;
- uint32_t section_length;
- EXPECT_EQ(decode_multipart_receive_req(
- msg, PLDM_MULTIPART_RECEIVE_REQ_BYTES, &pldm_type, &flag,
- &transfer_ctx, &transfer_handle, §ion_offset,
- §ion_length),
- PLDM_ERROR_INVALID_DATA);
-}
-
TEST(DecodeMultipartReceiveRequest, testDecodeRequestFailBadHandle)
{
constexpr uint8_t kPldmType = PLDM_BASE;