diff options
author | Brad King <brad.king@kitware.com> | 2023-08-18 13:00:14 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-08-18 13:00:14 (GMT) |
commit | 90df1e5da4eea8f07deacdbf67638c320801189f (patch) | |
tree | 1564ea5cd4ee70480c23fab205bc2c1a1f3125dd /Utilities/cmcppdap/src | |
parent | 01d2e5ed3a2f3078cf58aee52054881730726a0e (diff) | |
parent | 5d568df6b1841e1f3d7f1e5da0baacc804d8cd5b (diff) | |
download | CMake-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.cpp | 55 | ||||
-rw-r--r-- | Utilities/cmcppdap/src/content_stream.h | 8 | ||||
-rw-r--r-- | Utilities/cmcppdap/src/content_stream_test.cpp | 37 | ||||
-rw-r--r-- | Utilities/cmcppdap/src/session.cpp | 7 | ||||
-rw-r--r-- | Utilities/cmcppdap/src/socket.cpp | 5 | ||||
-rw-r--r-- | Utilities/cmcppdap/src/string_buffer.h | 16 |
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; } |