From 6861c00c813c61f9cc1ac8e6e617afc1b43fa1fd Mon Sep 17 00:00:00 2001
From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com>
Date: Mon, 17 Jul 2023 15:22:40 +0200
Subject: [PATCH] Improve validation on PID_PROPERTY_LIST deserialization
 (#3680)

* Refs #19116. Validate lengths before using them.

Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

* Refs #19116. Improve validation.

Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

---------

Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>
(cherry picked from commit 7c1c611f2f70ec238fbde30a9ed044d99191e4fb)

Co-authored-by: Miguel Company <miguelcompany@eprosima.com>
---
 .../core/policy/ParameterSerializer.hpp       | 53 +++++++++++++++----
 1 file changed, 42 insertions(+), 11 deletions(-)

diff --git a/src/cpp/fastdds/core/policy/ParameterSerializer.hpp b/src/cpp/fastdds/core/policy/ParameterSerializer.hpp
index 542453ee022..85ffe3f2e3e 100644
--- a/src/cpp/fastdds/core/policy/ParameterSerializer.hpp
+++ b/src/cpp/fastdds/core/policy/ParameterSerializer.hpp
@@ -637,39 +637,70 @@ inline bool ParameterSerializer<ParameterPropertyList_t>::read_content_from_cdr_
     parameter.length = parameter_length;
 
     uint32_t pos_ref = cdr_message->pos;
+    uint32_t max_pos = pos_ref + parameter_length;
+    uint32_t remain = parameter_length;
+    if ((max_pos > cdr_message->length) || (remain < sizeof(uint32_t)))
+    {
+        return false;
+    }
+
     uint32_t num_properties = 0;
     bool valid = fastrtps::rtps::CDRMessage::readUInt32(cdr_message, &num_properties);
+    remain -= sizeof(uint32_t);
     if (!valid)
     {
         return false;
     }
-    //properties_.reserve(parameter_length - 4);
 
-    for (size_t i = 0; i < num_properties; ++i)
+    for (uint32_t i = 0; i < num_properties; ++i)
     {
-        uint32_t property1_size = 0, alignment1 = 0, property2_size = 0, alignment2 = 0, str1_pos = 0;
+        uint32_t property1_size = 0, alignment1 = 0, property2_size = 0, alignment2 = 0, str1_pos = 0, str2_pos = 0;
 
-        valid &= fastrtps::rtps::CDRMessage::readUInt32(cdr_message, &property1_size);
+        // Read and validate size of property name
+        remain = max_pos - cdr_message->pos;
+        valid &= (remain >= sizeof(uint32_t)) && fastrtps::rtps::CDRMessage::readUInt32(cdr_message, &property1_size);
+        remain -= sizeof(uint32_t);
+        valid = valid && (remain >= property1_size);
         if (!valid)
         {
             return false;
         }
+
         str1_pos = cdr_message->pos;
+        cdr_message->pos += property1_size;
+        remain -= property1_size;
         alignment1 = ((property1_size + 3u) & ~3u) - property1_size;
-        cdr_message->pos += (property1_size + alignment1);
-        valid &= fastrtps::rtps::CDRMessage::readUInt32(cdr_message, &property2_size);
+        if (remain < alignment1)
+        {
+            return false;
+        }
+        cdr_message->pos += alignment1;
+        remain -= alignment1;
+
+        // Read and validate size of property value
+        valid &= (remain >= sizeof(uint32_t)) && fastrtps::rtps::CDRMessage::readUInt32(cdr_message, &property2_size);
+        remain -= sizeof(uint32_t);
+        valid = valid && (remain >= property2_size);
         if (!valid)
         {
             return false;
         }
-        parameter.push_back(
-            &cdr_message->buffer[str1_pos], property1_size,
-            &cdr_message->buffer[cdr_message->pos], property2_size);
 
+        str2_pos = cdr_message->pos;
+        cdr_message->pos += property2_size;
+        remain -= property2_size;
         alignment2 = ((property2_size + 3u) & ~3u) - property2_size;
-        cdr_message->pos += (property2_size + alignment2);
+        if (remain < alignment2)
+        {
+            return false;
+        }
+        cdr_message->pos += alignment2;
+        remain -= alignment2;
+
+        parameter.push_back(
+            &cdr_message->buffer[str1_pos], property1_size,
+            &cdr_message->buffer[str2_pos], property2_size);
     }
-    //Nproperties_ = num_properties;
 
     uint32_t length_diff = cdr_message->pos - pos_ref;
     valid &= (parameter_length >= length_diff);