diff --git a/Help/command/DEPRECATED_POLICY_VERSIONS.txt b/Help/command/DEPRECATED_POLICY_VERSIONS.txt new file mode 100644 index 000000000..7c6826004 --- /dev/null +++ b/Help/command/DEPRECATED_POLICY_VERSIONS.txt @@ -0,0 +1,15 @@ +.. versionchanged:: 3.27 + + Compatibility with versions of CMake older than 3.5 is deprecated. + Calls to :command:`cmake_minimum_required(VERSION)` or + :command:`cmake_policy(VERSION)` that do not specify at least + 3.5 as their policy version (optionally via ``...``) + will produce a deprecation warning in CMake 3.27 and above. + +.. versionchanged:: 3.19 + + Compatibility with versions of CMake older than 2.8.12 is deprecated. + Calls to :command:`cmake_minimum_required(VERSION)` or + :command:`cmake_policy(VERSION)` that do not specify at least + 2.8.12 as their policy version (optionally via ``...``) + will produce a deprecation warning in CMake 3.19 and above. diff --git a/Help/command/cmake_minimum_required.rst b/Help/command/cmake_minimum_required.rst index 031bd5690..de2c8f317 100644 --- a/Help/command/cmake_minimum_required.rst +++ b/Help/command/cmake_minimum_required.rst @@ -80,6 +80,8 @@ invokes which enables compatibility features for CMake 2.4 and lower. +.. include:: DEPRECATED_POLICY_VERSIONS.txt + See Also ^^^^^^^^ diff --git a/Help/command/cmake_policy.rst b/Help/command/cmake_policy.rst index cde74a733..d7880bc21 100644 --- a/Help/command/cmake_policy.rst +++ b/Help/command/cmake_policy.rst @@ -52,6 +52,8 @@ version and tells newer CMake versions to warn about their new policies. Note that the :command:`cmake_minimum_required(VERSION)` command implicitly calls ``cmake_policy(VERSION)`` too. +.. include:: DEPRECATED_POLICY_VERSIONS.txt + Setting Policies Explicitly ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/3.27.rst b/Help/release/3.27.rst index 561933a0b..7bcfc9a48 100644 --- a/Help/release/3.27.rst +++ b/Help/release/3.27.rst @@ -285,9 +285,9 @@ Changes made since CMake 3.27.0 include the following. to select the Windows 8.1 SDK. In CMake 3.27.[0-1] the ``version=`` field was limited to selecting Windows 10 SDKs. -3.27.3 ------- +3.27.3, 3.27.4 +-------------- -* This version made no changes to documented features or interfaces. +* These versions made no changes to documented features or interfaces. Some implementation updates were made to support ecosystem changes and/or fix regressions. diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 6c490960d..2cf98534a 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -402,9 +402,6 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} endif() endif() set(id_toolset_version_props "") - if(lang STREQUAL CXX OR lang STREQUAL C) - set(id_toolset_version_props "${id_toolset_version_props}") - endif() unset(id_sep) endif() endif() diff --git a/Modules/Compiler/LLVMFlang-Fortran.cmake b/Modules/Compiler/LLVMFlang-Fortran.cmake index 9e72b0689..291413ede 100644 --- a/Modules/Compiler/LLVMFlang-Fortran.cmake +++ b/Modules/Compiler/LLVMFlang-Fortran.cmake @@ -14,3 +14,7 @@ set(CMAKE_Fortran_MODDIR_FLAG "-module-dir") set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp") set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp") set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72") + +string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g") +string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g") +string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3") diff --git a/Modules/CompilerId/VS-10.vcxproj.in b/Modules/CompilerId/VS-10.vcxproj.in index fa324d821..adb9d49bf 100644 --- a/Modules/CompilerId/VS-10.vcxproj.in +++ b/Modules/CompilerId/VS-10.vcxproj.in @@ -18,8 +18,8 @@ @id_ToolsetVCTargetsDir@ @id_CustomGlobals@ - @id_toolset_version_props@ + @id_toolset_version_props@ @id_PreferredToolArchitecture@ diff --git a/Modules/FindZLIB.cmake b/Modules/FindZLIB.cmake index d0deb8778..4e7d5d665 100644 --- a/Modules/FindZLIB.cmake +++ b/Modules/FindZLIB.cmake @@ -175,25 +175,24 @@ unset(ZLIB_NAMES_DEBUG) mark_as_advanced(ZLIB_INCLUDE_DIR) if(ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h") - file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$") - - string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}") - string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}") - string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}") - set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}") - - # only append a TWEAK version if it exists: + file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$") + if(ZLIB_H MATCHES "ZLIB_VERSION \"(([0-9]+)\\.([0-9]+)(\\.([0-9]+)(\\.([0-9]+))?)?)") + set(ZLIB_VERSION_STRING "${CMAKE_MATCH_1}") + set(ZLIB_VERSION_MAJOR "${CMAKE_MATCH_2}") + set(ZLIB_VERSION_MINOR "${CMAKE_MATCH_3}") + set(ZLIB_VERSION_PATCH "${CMAKE_MATCH_5}") + set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_7}") + else() + set(ZLIB_VERSION_STRING "") + set(ZLIB_VERSION_MAJOR "") + set(ZLIB_VERSION_MINOR "") + set(ZLIB_VERSION_PATCH "") set(ZLIB_VERSION_TWEAK "") - if( "${ZLIB_H}" MATCHES "ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+)") - set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}") - string(APPEND ZLIB_VERSION_STRING ".${ZLIB_VERSION_TWEAK}") - endif() - - set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}") - set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}") - set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}") - - set(ZLIB_VERSION ${ZLIB_VERSION_STRING}) + endif() + set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}") + set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}") + set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}") + set(ZLIB_VERSION "${ZLIB_VERSION_STRING}") endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 871e0d5b8..196067839 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 27) -set(CMake_VERSION_PATCH 3) +set(CMake_VERSION_PATCH 4) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) @@ -21,7 +21,7 @@ endif() if(NOT CMake_VERSION_NO_GIT) # If this source was exported by 'git archive', use its commit info. - set(git_info [==[a69c783749 CMake 3.27.3]==]) + set(git_info [==[c3977582b7 CMake 3.27.4]==]) # Otherwise, try to identify the current development source version. if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* " diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 7fe814ae3..4c80d4b4c 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1360,7 +1360,9 @@ static const struct ListNode : public cmGeneratorExpressionNode try { auto list = GetList(args.front()); args.advance(2); - list.insert_items(index, args.begin(), args.end()); + list.insert_items(index, args.begin(), args.end(), + cmList::ExpandElements::No, + cmList::EmptyElements::Yes); return list.to_string(); } catch (std::out_of_range& e) { reportError(ctx, cnt->GetOriginalExpression(), e.what()); diff --git a/Source/cmList.h b/Source/cmList.h index 798b9842b..df450fdf4 100644 --- a/Source/cmList.h +++ b/Source/cmList.h @@ -740,9 +740,20 @@ public: // Throw std::out_of_range if index is invalid template cmList& insert_items(index_type index, InputIterator first, - InputIterator last) + InputIterator last, + ExpandElements expandElements = ExpandElements::Yes, + EmptyElements emptyElements = EmptyElements::No) { - this->insert(this->begin() + this->ComputeInsertIndex(index), first, last); + this->insert(this->begin() + this->ComputeInsertIndex(index), first, last, + expandElements, emptyElements); + return *this; + } + template + cmList& insert_items(index_type index, InputIterator first, + InputIterator last, EmptyElements emptyElements) + { + this->insert(this->begin() + this->ComputeInsertIndex(index), first, last, + ExpandElements::Yes, emptyElements); return *this; } cmList& insert_items(index_type index, diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index acffa2ec8..ebf58418c 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -375,7 +375,8 @@ bool HandleInsertCommand(std::vector const& args, } try { - list->insert_items(index, args.begin() + 3, args.end()); + list->insert_items(index, args.begin() + 3, args.end(), + cmList::ExpandElements::No, cmList::EmptyElements::Yes); status.GetMakefile().AddDefinition(listName, list->to_string()); return true; } catch (std::out_of_range& e) { diff --git a/Tests/CMakeTests/ListTest.cmake.in b/Tests/CMakeTests/ListTest.cmake.in index 76737e578..0120c8470 100644 --- a/Tests/CMakeTests/ListTest.cmake.in +++ b/Tests/CMakeTests/ListTest.cmake.in @@ -161,3 +161,24 @@ foreach (_pol ${thelist}) message(SEND_ERROR "returned element '${thevalue}', but expected '${_pol}'") endif() endforeach (_pol) + +block(SCOPE_FOR POLICIES) + cmake_policy(SET CMP0007 NEW) + set(result andy bill brad ken bob) + list(INSERT result 1 "") + TEST("INSERT result 1 \"\"" "andy;;bill;brad;ken;bob") + list(INSERT result 4 ";") + TEST("INSERT result 1 ;" "andy;;bill;brad;;;ken;bob") + list(INSERT result 0 "x") + TEST("INSERT result 1 x" "x;andy;;bill;brad;;;ken;bob") +endblock() +block(SCOPE_FOR POLICIES) + cmake_policy(SET CMP0007 OLD) + set(result andy bill brad ken bob) + list(INSERT result 1 "") + TEST("INSERT result 1 \"\"" "andy;;bill;brad;ken;bob") + list(INSERT result 4 ";") + TEST("INSERT result 1 ;" "andy;bill;brad;ken;;;bob") + list(INSERT result 0 "x") + TEST("INSERT result 1 x" "x;andy;bill;brad;ken;bob") +endblock() diff --git a/Tests/RunCMake/GenEx-LIST/INSERT.cmake.in b/Tests/RunCMake/GenEx-LIST/INSERT.cmake.in index d3bb9b9b1..48add615e 100644 --- a/Tests/RunCMake/GenEx-LIST/INSERT.cmake.in +++ b/Tests/RunCMake/GenEx-LIST/INSERT.cmake.in @@ -46,5 +46,52 @@ if (NOT output STREQUAL listvar) list (APPEND errors "returns bad value: ${output}") endif() +block(SCOPE_FOR POLICIES) + cmake_policy(SET CMP0007 NEW) + + set(listvar "0;1;2;3;4") + list(INSERT listvar 1 "") + set (output "$") + if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") + endif() + + list(INSERT listvar 4 ";") + set (output "$") + if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") + endif() + + list(INSERT listvar 0 "x") + set (output "$") + if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") + endif() +endblock() +block(SCOPE_FOR POLICIES) + set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "") + cmake_policy(SET CMP0007 OLD) + + set(listvar "0;1;2;3;4") + list(INSERT listvar 1 "") + set (output "$") + if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") + endif() + + list(INSERT listvar 4 ";") + set (output "$") + if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") + endif() + + list(INSERT listvar 0 "x") + set (output "$") + if (NOT output STREQUAL listvar) + list (APPEND errors "returns bad value: ${output}") + endif() + + unset(CMAKE_WARN_DEPRECATED CACHE) +endblock() check_errors("LIST:INSERT..." ${errors}) diff --git a/Utilities/Scripts/update-cppdap.bash b/Utilities/Scripts/update-cppdap.bash index fd4f8cbcf..b5df7a5d9 100755 --- a/Utilities/Scripts/update-cppdap.bash +++ b/Utilities/Scripts/update-cppdap.bash @@ -8,7 +8,7 @@ readonly name="cppdap" readonly ownership="cppdap Upstream " readonly subtree="Utilities/cmcppdap" readonly repo="https://github.com/google/cppdap.git" -readonly tag="03cc18678ed2ed8b2424ec99dee7e4655d876db5" # 2023-05-25 +readonly tag="cc2f2058846bb29e18fdadf455d5f5af71b2554f" # 2023-08-17 readonly shortlog=false readonly paths=" LICENSE @@ -23,6 +23,7 @@ extract_source () { echo "* -whitespace" > .gitattributes fromdos LICENSE include/dap/* src/* echo "" >> LICENSE + echo "" >> src/content_stream.cpp echo "" >> src/nlohmann_json_serializer.h popd } diff --git a/Utilities/cmcppdap/include/dap/session.h b/Utilities/cmcppdap/include/dap/session.h index 39338862d..96db04b7d 100644 --- a/Utilities/cmcppdap/include/dap/session.h +++ b/Utilities/cmcppdap/include/dap/session.h @@ -103,6 +103,14 @@ ResponseOrError& ResponseOrError::operator=(ResponseOrError&& other) { // Session //////////////////////////////////////////////////////////////////////////////// +// An enum flag that controls how the Session handles invalid data. +enum OnInvalidData { + // Ignore invalid data. + kIgnore, + // Close the underlying reader when invalid data is received. + kClose, +}; + // Session implements a DAP client or server endpoint. // The general usage is as follows: // (1) Create a session with Session::create(). @@ -144,6 +152,9 @@ class Session { // create() constructs and returns a new Session. static std::unique_ptr create(); + // Sets how the Session handles invalid data. + virtual void setOnInvalidData(OnInvalidData) = 0; + // onError() registers a error handler that will be called whenever a protocol // error is encountered. // Only one error handler can be bound at any given time, and later calls diff --git a/Utilities/cmcppdap/src/content_stream.cpp b/Utilities/cmcppdap/src/content_stream.cpp index 05d7f4767..c8a5f3ebf 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) {} +ContentReader::ContentReader( + const std::shared_ptr& 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 1fd08491c..eee998ed9 100644 --- a/Utilities/cmcppdap/src/content_stream.h +++ b/Utilities/cmcppdap/src/content_stream.h @@ -21,6 +21,8 @@ #include +#include "dap/session.h" + namespace dap { // Forward declarations @@ -30,7 +32,8 @@ class Writer; class ContentReader { public: ContentReader() = default; - ContentReader(const std::shared_ptr&); + ContentReader(const std::shared_ptr&, + 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; std::deque 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 80939a872..3f0047230 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::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 d88a697b3..5bf22c9cc 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 inbox; std::atomic 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 12113107a..e9402d3b3 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 cdd6c41c6..1c381971a 100644 --- a/Utilities/cmcppdap/src/string_buffer.h +++ b/Utilities/cmcppdap/src/string_buffer.h @@ -19,7 +19,8 @@ #include // std::min #include // memcpy -#include // std::unique_ptr +#include +#include // std::unique_ptr #include namespace dap { @@ -39,6 +40,7 @@ class StringBuffer : public virtual Reader, public virtual Writer { private: std::string str; + std::deque 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(buffer); str.append(chars, chars + bytes); + chunk_lengths.push_back(bytes); return true; }