summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcppdap/src
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2023-08-18 13:00:14 (GMT)
committerBrad King <brad.king@kitware.com>2023-08-18 13:00:14 (GMT)
commit90df1e5da4eea8f07deacdbf67638c320801189f (patch)
tree1564ea5cd4ee70480c23fab205bc2c1a1f3125dd /Utilities/cmcppdap/src
parent01d2e5ed3a2f3078cf58aee52054881730726a0e (diff)
parent5d568df6b1841e1f3d7f1e5da0baacc804d8cd5b (diff)
downloadCMake-90df1e5da4eea8f07deacdbf67638c320801189f.zip
CMake-90df1e5da4eea8f07deacdbf67638c320801189f.tar.gz
CMake-90df1e5da4eea8f07deacdbf67638c320801189f.tar.bz2
Merge branch 'upstream-cppdap' into update-cppdap
# By cppdap Upstream * upstream-cppdap: cppdap 2023-08-17 (cc2f2058)
Diffstat (limited to 'Utilities/cmcppdap/src')
-rw-r--r--Utilities/cmcppdap/src/content_stream.cpp55
-rw-r--r--Utilities/cmcppdap/src/content_stream.h8
-rw-r--r--Utilities/cmcppdap/src/content_stream_test.cpp37
-rw-r--r--Utilities/cmcppdap/src/session.cpp7
-rw-r--r--Utilities/cmcppdap/src/socket.cpp5
-rw-r--r--Utilities/cmcppdap/src/string_buffer.h16
6 files changed, 92 insertions, 36 deletions
diff --git a/Utilities/cmcppdap/src/content_stream.cpp b/Utilities/cmcppdap/src/content_stream.cpp
index 05d7f47..c8a5f3e 100644
--- a/Utilities/cmcppdap/src/content_stream.cpp
+++ b/Utilities/cmcppdap/src/content_stream.cpp
@@ -24,12 +24,15 @@ namespace dap {
////////////////////////////////////////////////////////////////////////////////
// ContentReader
////////////////////////////////////////////////////////////////////////////////
-ContentReader::ContentReader(const std::shared_ptr<Reader>& reader)
- : reader(reader) {}
+ContentReader::ContentReader(
+ const std::shared_ptr<Reader>& reader,
+ OnInvalidData on_invalid_data /* = OnInvalidData::kIgnore */)
+ : reader(reader), on_invalid_data(on_invalid_data) {}
ContentReader& ContentReader::operator=(ContentReader&& rhs) noexcept {
buf = std::move(rhs.buf);
reader = std::move(rhs.reader);
+ on_invalid_data = std::move(rhs.on_invalid_data);
return *this;
}
@@ -44,17 +47,19 @@ void ContentReader::close() {
}
std::string ContentReader::read() {
- matched_idx = 0;
-
// Find Content-Length header prefix
- if (!scan("Content-Length:")) {
- return "";
+ if (on_invalid_data == kClose) {
+ if (!match("Content-Length:")) {
+ return badHeader();
+ }
+ } else {
+ if (!scan("Content-Length:")) {
+ return "";
+ }
}
-
// Skip whitespace and tabs
while (matchAny(" \t")) {
}
-
// Parse length
size_t len = 0;
while (true) {
@@ -68,20 +73,16 @@ std::string ContentReader::read() {
if (len == 0) {
return "";
}
+
// Expect \r\n\r\n
if (!match("\r\n\r\n")) {
- return "";
+ return badHeader();
}
// Read message
- if (!buffer(len + matched_idx)) {
+ if (!buffer(len)) {
return "";
}
-
- for (size_t i = 0; i < matched_idx; i++) {
- buf.pop_front();
- }
-
std::string out;
out.reserve(len);
for (size_t i = 0; i < len; i++) {
@@ -107,17 +108,18 @@ bool ContentReader::scan(const char* str) {
}
bool ContentReader::match(const uint8_t* seq, size_t len) {
- if (!buffer(len + matched_idx)) {
+ if (!buffer(len)) {
return false;
}
- auto it = matched_idx;
+ auto it = buf.begin();
for (size_t i = 0; i < len; i++, it++) {
- if (buf[it] != seq[i]) {
+ if (*it != seq[i]) {
return false;
}
}
-
- matched_idx += len;
+ for (size_t i = 0; i < len; i++) {
+ buf.pop_front();
+ }
return true;
}
@@ -127,12 +129,12 @@ bool ContentReader::match(const char* str) {
}
char ContentReader::matchAny(const char* chars) {
- if (!buffer(1 + matched_idx)) {
+ if (!buffer(1)) {
return false;
}
- int c = buf[matched_idx];
+ int c = buf.front();
if (auto p = strchr(chars, c)) {
- matched_idx++;
+ buf.pop_front();
return *p;
}
return 0;
@@ -158,6 +160,13 @@ bool ContentReader::buffer(size_t bytes) {
return true;
}
+std::string ContentReader::badHeader() {
+ if (on_invalid_data == kClose) {
+ close();
+ }
+ return "";
+}
+
////////////////////////////////////////////////////////////////////////////////
// ContentWriter
////////////////////////////////////////////////////////////////////////////////
diff --git a/Utilities/cmcppdap/src/content_stream.h b/Utilities/cmcppdap/src/content_stream.h
index 1fd0849..eee998e 100644
--- a/Utilities/cmcppdap/src/content_stream.h
+++ b/Utilities/cmcppdap/src/content_stream.h
@@ -21,6 +21,8 @@
#include <stdint.h>
+#include "dap/session.h"
+
namespace dap {
// Forward declarations
@@ -30,7 +32,8 @@ class Writer;
class ContentReader {
public:
ContentReader() = default;
- ContentReader(const std::shared_ptr<Reader>&);
+ ContentReader(const std::shared_ptr<Reader>&,
+ const OnInvalidData on_invalid_data = kIgnore);
ContentReader& operator=(ContentReader&&) noexcept;
bool isOpen();
@@ -44,10 +47,11 @@ class ContentReader {
bool match(const char* str);
char matchAny(const char* chars);
bool buffer(size_t bytes);
+ std::string badHeader();
std::shared_ptr<Reader> reader;
std::deque<uint8_t> buf;
- uint32_t matched_idx = 0;
+ OnInvalidData on_invalid_data;
};
class ContentWriter {
diff --git a/Utilities/cmcppdap/src/content_stream_test.cpp b/Utilities/cmcppdap/src/content_stream_test.cpp
index 80939a8..3f00472 100644
--- a/Utilities/cmcppdap/src/content_stream_test.cpp
+++ b/Utilities/cmcppdap/src/content_stream_test.cpp
@@ -84,16 +84,43 @@ TEST(ContentStreamTest, ShortRead) {
TEST(ContentStreamTest, PartialReadAndParse) {
auto sb = std::make_shared<dap::StringBuffer>();
- dap::ContentReader cs(sb);
sb->write("Content");
- ASSERT_EQ(cs.read(), "");
sb->write("-Length: ");
- ASSERT_EQ(cs.read(), "");
sb->write("26");
- ASSERT_EQ(cs.read(), "");
sb->write("\r\n\r\n");
- ASSERT_EQ(cs.read(), "");
sb->write("Content payload number one");
+
+ dap::ContentReader cs(sb);
ASSERT_EQ(cs.read(), "Content payload number one");
ASSERT_EQ(cs.read(), "");
}
+
+TEST(ContentStreamTest, HttpRequest) {
+ const char* const part1 =
+ "POST / HTTP/1.1\r\n"
+ "Host: localhost:8001\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: 99\r\n";
+ const char* const part2 =
+ "Pragma: no-cache\r\n"
+ "Cache-Control: no-cache\r\n"
+ "Content-Type: text/plain;charset=UTF-8\r\n"
+ "Accept: */*\r\n"
+ "Origin: null\r\n"
+ "Sec-Fetch-Site: cross-site\r\n"
+ "Sec-Fetch-Mode: cors\r\n"
+ "Sec-Fetch-Dest: empty\r\n"
+ "Accept-Encoding: gzip, deflate, br\r\n"
+ "Accept-Language: en-US,en;q=0.9\r\n"
+ "\r\n"
+ "{\"type\":\"request\",\"command\":\"launch\",\"arguments\":{\"cmd\":\"/"
+ "bin/sh -c 'echo remote code execution'\"}}";
+
+ auto sb = dap::StringBuffer::create();
+ sb->write(part1);
+ sb->write(part2);
+
+ dap::ContentReader cr(std::move(sb), dap::kClose);
+ ASSERT_EQ(cr.read(), "");
+ ASSERT_FALSE(cr.isOpen());
+}
diff --git a/Utilities/cmcppdap/src/session.cpp b/Utilities/cmcppdap/src/session.cpp
index d88a697..5bf22c9 100644
--- a/Utilities/cmcppdap/src/session.cpp
+++ b/Utilities/cmcppdap/src/session.cpp
@@ -35,6 +35,10 @@ namespace {
class Impl : public dap::Session {
public:
+ void setOnInvalidData(dap::OnInvalidData onInvalidData_) override {
+ this->onInvalidData = onInvalidData_;
+ }
+
void onError(const ErrorHandler& handler) override { handlers.put(handler); }
void registerHandler(const dap::TypeInfo* typeinfo,
@@ -69,7 +73,7 @@ class Impl : public dap::Session {
return;
}
- reader = dap::ContentReader(r);
+ reader = dap::ContentReader(r, this->onInvalidData);
writer = dap::ContentWriter(w);
}
@@ -490,6 +494,7 @@ class Impl : public dap::Session {
dap::Chan<Payload> inbox;
std::atomic<uint32_t> nextSeq = {1};
std::mutex sendMutex;
+ dap::OnInvalidData onInvalidData = dap::kIgnore;
};
} // anonymous namespace
diff --git a/Utilities/cmcppdap/src/socket.cpp b/Utilities/cmcppdap/src/socket.cpp
index 1211310..e9402d3 100644
--- a/Utilities/cmcppdap/src/socket.cpp
+++ b/Utilities/cmcppdap/src/socket.cpp
@@ -108,7 +108,6 @@ class dap::Socket::Shared : public dap::ReaderWriter {
return out;
}
- freeaddrinfo(info);
term();
return nullptr;
}
@@ -117,7 +116,9 @@ class dap::Socket::Shared : public dap::ReaderWriter {
Shared(addrinfo* info, SOCKET socket) : info(info), s(socket) {}
~Shared() {
- freeaddrinfo(info);
+ if (info) {
+ freeaddrinfo(info);
+ }
close();
term();
}
diff --git a/Utilities/cmcppdap/src/string_buffer.h b/Utilities/cmcppdap/src/string_buffer.h
index cdd6c41..1c38197 100644
--- a/Utilities/cmcppdap/src/string_buffer.h
+++ b/Utilities/cmcppdap/src/string_buffer.h
@@ -19,7 +19,8 @@
#include <algorithm> // std::min
#include <cstring> // memcpy
-#include <memory> // std::unique_ptr
+#include <deque>
+#include <memory> // std::unique_ptr
#include <string>
namespace dap {
@@ -39,6 +40,7 @@ class StringBuffer : public virtual Reader, public virtual Writer {
private:
std::string str;
+ std::deque<size_t> chunk_lengths;
bool closed = false;
};
@@ -62,12 +64,19 @@ std::string StringBuffer::string() const {
}
size_t StringBuffer::read(void* buffer, size_t bytes) {
- if (closed || bytes == 0 || str.size() == 0) {
+ if (closed || bytes == 0 || str.size() == 0 || chunk_lengths.size() == 0) {
return 0;
}
- auto len = std::min(bytes, str.size());
+ size_t& chunk_length = chunk_lengths.front();
+
+ auto len = std::min(bytes, chunk_length);
memcpy(buffer, str.data(), len);
str = std::string(str.begin() + len, str.end());
+ if (bytes < chunk_length) {
+ chunk_length -= bytes;
+ } else {
+ chunk_lengths.pop_front();
+ }
return len;
}
@@ -77,6 +86,7 @@ bool StringBuffer::write(const void* buffer, size_t bytes) {
}
auto chars = reinterpret_cast<const char*>(buffer);
str.append(chars, chars + bytes);
+ chunk_lengths.push_back(bytes);
return true;
}