oem-ibm: avoid file read range integer overflow

Fix IBM OEM file-read range validation to avoid overflowing the
32-bit offset + length boundary check.

A PLDM peer could issue ReadFile with a valid small offset and a
large length, such as offset=1 and length=UINT32_MAX. The previous
check computed offset + length directly, allowing the sum to wrap and
skip the clamp logic. In the generic read path this could trigger an
attempt to allocate a response near 4 GiB, causing std::bad_alloc and
terminating pldmd.

Use the overflow-safe form length > fileSize - offset after the
existing offset >= fileSize validation. This preserves the existing
clamp-at-EOF behavior while fixing all affected IBM file-read paths,
including generic, DMA, and file-by-type reads.

Change-Id: I774e0a16b9bf855b73b1456cec9a00e93fcc4cad
Signed-off-by: Manjeet Singh <itsmanjeet1998@gmail.com>
diff --git a/oem/ibm/libpldmresponder/file_io.cpp b/oem/ibm/libpldmresponder/file_io.cpp
index 044ba0f..4fb722d 100644
--- a/oem/ibm/libpldmresponder/file_io.cpp
+++ b/oem/ibm/libpldmresponder/file_io.cpp
@@ -421,7 +421,7 @@
         return response;
     }
 
-    if (offset + length > fileSize)
+    if (length > fileSize - offset)
     {
         length = fileSize - offset;
     }
@@ -687,7 +687,7 @@
         return response;
     }
 
-    if (offset + length > fileSize)
+    if (length > fileSize - offset)
     {
         length = fileSize - offset;
     }
diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp
index aedee02..2c41c9e 100644
--- a/oem/ibm/libpldmresponder/file_io_by_type.cpp
+++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp
@@ -89,7 +89,7 @@
                 "OFFSET", offset, "SIZE", fileSize, "FILE_HANDLE", fileHandle);
             return PLDM_DATA_OUT_OF_RANGE;
         }
-        if (offset + length > fileSize)
+        if (length > fileSize - offset)
         {
             length = fileSize - offset;
         }
@@ -199,7 +199,7 @@
         return PLDM_DATA_OUT_OF_RANGE;
     }
 
-    if (offset + length > fileSize)
+    if (length > fileSize - offset)
     {
         length = fileSize - offset;
     }
diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.cpp b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
index 7d3daf9..ae4181b 100644
--- a/oem/ibm/libpldmresponder/file_io_type_pel.cpp
+++ b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
@@ -152,7 +152,7 @@
                 "OFFSET", offset, "SIZE", fileSize, "FILE_HANDLE", fileHandle);
             return PLDM_DATA_OUT_OF_RANGE;
         }
-        if (offset + length > fileSize)
+        if (length > static_cast<uint64_t>(fileSize - offset))
         {
             length = fileSize - offset;
         }
diff --git a/oem/ibm/test/libpldmresponder_fileio_test.cpp b/oem/ibm/test/libpldmresponder_fileio_test.cpp
index b59b52a..0ce1d02 100644
--- a/oem/ibm/test/libpldmresponder_fileio_test.cpp
+++ b/oem/ibm/test/libpldmresponder_fileio_test.cpp
@@ -712,6 +712,15 @@
     ASSERT_EQ(0, memcmp(response->file_data, buffer.data(),
                         (fileSize - request->offset)));
 
+    // A large length must be clamped without wrapping offset + length.
+    request->offset = 1;
+    request->length = UINT32_MAX;
+    responseMsg = handler.readFile(requestMsgPtr, payload_length);
+    response = reinterpret_cast<pldm_read_file_resp*>(
+        responseMsg.data() + sizeof(pldm_msg_hdr));
+    ASSERT_EQ(response->completion_code, PLDM_SUCCESS);
+    ASSERT_EQ(response->length, fileSize - request->offset);
+
     table.clear();
 }
 
@@ -996,4 +1005,11 @@
     ASSERT_EQ(length, in.size());
     ASSERT_EQ(response.size(), in.size());
     ASSERT_EQ(std::equal(in.begin(), in.end(), response.begin()), true);
+
+    length = UINT32_MAX;
+    response.clear();
+    rc = handler.readFile(tmplt, 1, length, response);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(length, in.size() - 1);
+    ASSERT_EQ(response.size(), in.size() - 1);
 }