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