This is an automated email from the ASF dual-hosted git repository.

jiangtian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 1aba8731e85 enhance cppclient tsblock deserialize validation (#17464)
1aba8731e85 is described below

commit 1aba8731e85f65d60baefabb7f7423b0ff1a9c24
Author: Hongzhi Gao <[email protected]>
AuthorDate: Wed Apr 15 15:05:16 2026 +0800

    enhance cppclient tsblock deserialize validation (#17464)
    
    * fix tsblock deserialize
    
    * fix ut error on win
    
    * Revert "fix ut error on win"
    
    This reverts commit 34b8de482c864abd64d721bdd51fe08e18b742b8.
---
 iotdb-client/client-cpp/src/main/ColumnDecoder.cpp |  3 +++
 iotdb-client/client-cpp/src/main/Common.cpp        | 20 ++++++++++++++++++--
 iotdb-client/client-cpp/src/main/TsBlock.cpp       | 12 ++++++++++++
 iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp |  7 +++++++
 4 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/iotdb-client/client-cpp/src/main/ColumnDecoder.cpp 
b/iotdb-client/client-cpp/src/main/ColumnDecoder.cpp
index e45cb49409a..32f29d876f3 100644
--- a/iotdb-client/client-cpp/src/main/ColumnDecoder.cpp
+++ b/iotdb-client/client-cpp/src/main/ColumnDecoder.cpp
@@ -151,6 +151,9 @@ std::unique_ptr<Column> 
BinaryArrayColumnDecoder::readColumn(
         if (!nullIndicators.empty() && nullIndicators[i]) continue;
 
         int32_t length = buffer.getInt();
+        if (length < 0) {
+            throw IoTDBException("BinaryArrayColumnDecoder: negative TEXT 
length");
+        }
 
         std::vector<uint8_t> value(length);
         for (int32_t j = 0; j < length; j++) {
diff --git a/iotdb-client/client-cpp/src/main/Common.cpp 
b/iotdb-client/client-cpp/src/main/Common.cpp
index 56dc9683057..f7eeb2a218e 100644
--- a/iotdb-client/client-cpp/src/main/Common.cpp
+++ b/iotdb-client/client-cpp/src/main/Common.cpp
@@ -293,6 +293,10 @@ double MyStringBuffer::getDouble() {
 }
 
 char MyStringBuffer::getChar() {
+    if (pos >= str.size()) {
+        throw IoTDBException("MyStringBuffer::getChar: read past end (pos=" + 
std::to_string(pos) +
+                             ", size=" + std::to_string(str.size()) + ")");
+    }
     return str[pos++];
 }
 
@@ -301,8 +305,16 @@ bool MyStringBuffer::getBool() {
 }
 
 std::string MyStringBuffer::getString() {
-    size_t len = getInt();
-    size_t tmpPos = pos;
+    const int lenInt = getInt();
+    if (lenInt < 0) {
+        throw IoTDBException("MyStringBuffer::getString: negative length");
+    }
+    const size_t len = static_cast<size_t>(lenInt);
+    if (pos > str.size() || len > str.size() - pos) {
+        throw IoTDBException("MyStringBuffer::getString: length exceeds buffer 
(pos=" + std::to_string(pos) +
+                             ", len=" + std::to_string(len) + ", size=" + 
std::to_string(str.size()) + ")");
+    }
+    const size_t tmpPos = pos;
     pos += len;
     return str.substr(tmpPos, len);
 }
@@ -351,6 +363,10 @@ void MyStringBuffer::checkBigEndian() {
 }
 
 const char* MyStringBuffer::getOrderedByte(size_t len) {
+    if (pos > str.size() || len > str.size() - pos) {
+        throw IoTDBException("MyStringBuffer::getOrderedByte: read past end 
(pos=" + std::to_string(pos) +
+                             ", len=" + std::to_string(len) + ", size=" + 
std::to_string(str.size()) + ")");
+    }
     const char* p = nullptr;
     if (isBigEndian) {
         p = str.c_str() + pos;
diff --git a/iotdb-client/client-cpp/src/main/TsBlock.cpp 
b/iotdb-client/client-cpp/src/main/TsBlock.cpp
index 7c2bac272a6..92afbef3f27 100644
--- a/iotdb-client/client-cpp/src/main/TsBlock.cpp
+++ b/iotdb-client/client-cpp/src/main/TsBlock.cpp
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+#include <cstdint>
 #include <stdexcept>
 #include <algorithm>
 #include "TsBlock.h"
@@ -34,6 +35,14 @@ std::shared_ptr<TsBlock> TsBlock::deserialize(const 
std::string& data) {
 
     // Read value column count
     int32_t valueColumnCount = buffer.getInt();
+    if (valueColumnCount < 0) {
+        throw IoTDBException("TsBlock::deserialize: negative 
valueColumnCount");
+    }
+    const int64_t minHeaderBytes =
+        9LL + 2LL * static_cast<int64_t>(valueColumnCount);
+    if (minHeaderBytes > static_cast<int64_t>(data.size())) {
+        throw IoTDBException("TsBlock::deserialize: truncated header");
+    }
 
     // Read value column data types
     std::vector<TSDataType::TSDataType> valueColumnDataTypes(valueColumnCount);
@@ -43,6 +52,9 @@ std::shared_ptr<TsBlock> TsBlock::deserialize(const 
std::string& data) {
 
     // Read position count
     int32_t positionCount = buffer.getInt();
+    if (positionCount < 0) {
+        throw IoTDBException("TsBlock::deserialize: negative positionCount");
+    }
 
     // Read column encodings
     std::vector<ColumnEncoding> columnEncodings(valueColumnCount + 1);
diff --git a/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp 
b/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
index af7f13855a4..c5e6e906083 100644
--- a/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
+++ b/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
@@ -20,6 +20,7 @@
 #include "catch.hpp"
 #include "Session.h"
 #include "SessionBuilder.h"
+#include "TsBlock.h"
 
 using namespace std;
 
@@ -858,4 +859,10 @@ TEST_CASE("UrlUtils - parseTEndPointIpv4AndIpv6Url", 
"[UrlUtils]") {
         
REQUIRE_TENDPOINT(UrlUtils::parseTEndPointIpv4AndIpv6Url("localhost:0"), 
"localhost", 0);
         
REQUIRE_TENDPOINT(UrlUtils::parseTEndPointIpv4AndIpv6Url("127.0.0.1:65535"), 
"127.0.0.1", 65535);
     }
+}
+
+TEST_CASE("TsBlock deserialize rejects truncated malicious payload", 
"[TsBlockDeserialize]") {
+    std::string data(18, '\0');
+    data[3] = '\x10';
+    REQUIRE_THROWS_AS(TsBlock::deserialize(data), IoTDBException);
 }
\ No newline at end of file

Reply via email to