New upstream version 3.27.4
This commit is contained in:
parent
ad8253d840
commit
75c9b0d3bf
15
Help/command/DEPRECATED_POLICY_VERSIONS.txt
Normal file
15
Help/command/DEPRECATED_POLICY_VERSIONS.txt
Normal file
@ -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 ``...<max>``)
|
||||||
|
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 ``...<max>``)
|
||||||
|
will produce a deprecation warning in CMake 3.19 and above.
|
@ -80,6 +80,8 @@ invokes
|
|||||||
|
|
||||||
which enables compatibility features for CMake 2.4 and lower.
|
which enables compatibility features for CMake 2.4 and lower.
|
||||||
|
|
||||||
|
.. include:: DEPRECATED_POLICY_VERSIONS.txt
|
||||||
|
|
||||||
See Also
|
See Also
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ version and tells newer CMake versions to warn about their new policies.
|
|||||||
Note that the :command:`cmake_minimum_required(VERSION)`
|
Note that the :command:`cmake_minimum_required(VERSION)`
|
||||||
command implicitly calls ``cmake_policy(VERSION)`` too.
|
command implicitly calls ``cmake_policy(VERSION)`` too.
|
||||||
|
|
||||||
|
.. include:: DEPRECATED_POLICY_VERSIONS.txt
|
||||||
|
|
||||||
Setting Policies Explicitly
|
Setting Policies Explicitly
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -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
|
to select the Windows 8.1 SDK. In CMake 3.27.[0-1] the ``version=`` field
|
||||||
was limited to selecting Windows 10 SDKs.
|
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
|
Some implementation updates were made to support ecosystem changes
|
||||||
and/or fix regressions.
|
and/or fix regressions.
|
||||||
|
@ -402,9 +402,6 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
set(id_toolset_version_props "<Import Project=\"${CMAKE_GENERATOR_INSTANCE}\\VC\\Auxiliary\\Build${id_sep}${CMAKE_VS_PLATFORM_TOOLSET_VERSION}\\Microsoft.VCToolsVersion.${CMAKE_VS_PLATFORM_TOOLSET_VERSION}.props\" />")
|
set(id_toolset_version_props "<Import Project=\"${CMAKE_GENERATOR_INSTANCE}\\VC\\Auxiliary\\Build${id_sep}${CMAKE_VS_PLATFORM_TOOLSET_VERSION}\\Microsoft.VCToolsVersion.${CMAKE_VS_PLATFORM_TOOLSET_VERSION}.props\" />")
|
||||||
if(lang STREQUAL CXX OR lang STREQUAL C)
|
|
||||||
set(id_toolset_version_props "<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />${id_toolset_version_props}")
|
|
||||||
endif()
|
|
||||||
unset(id_sep)
|
unset(id_sep)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
@ -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_ON "-cpp")
|
||||||
set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
|
set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
|
||||||
set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
|
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")
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
@id_ToolsetVCTargetsDir@
|
@id_ToolsetVCTargetsDir@
|
||||||
@id_CustomGlobals@
|
@id_CustomGlobals@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@id_toolset_version_props@
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
@id_toolset_version_props@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@id_PreferredToolArchitecture@
|
@id_PreferredToolArchitecture@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
@ -175,25 +175,24 @@ unset(ZLIB_NAMES_DEBUG)
|
|||||||
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
||||||
|
|
||||||
if(ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
if(ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
||||||
file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$")
|
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]+))?)?)")
|
||||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}")
|
set(ZLIB_VERSION_STRING "${CMAKE_MATCH_1}")
|
||||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}")
|
set(ZLIB_VERSION_MAJOR "${CMAKE_MATCH_2}")
|
||||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}")
|
set(ZLIB_VERSION_MINOR "${CMAKE_MATCH_3}")
|
||||||
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}")
|
set(ZLIB_VERSION_PATCH "${CMAKE_MATCH_5}")
|
||||||
|
set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_7}")
|
||||||
# only append a TWEAK version if it exists:
|
else()
|
||||||
|
set(ZLIB_VERSION_STRING "")
|
||||||
|
set(ZLIB_VERSION_MAJOR "")
|
||||||
|
set(ZLIB_VERSION_MINOR "")
|
||||||
|
set(ZLIB_VERSION_PATCH "")
|
||||||
set(ZLIB_VERSION_TWEAK "")
|
set(ZLIB_VERSION_TWEAK "")
|
||||||
if( "${ZLIB_H}" MATCHES "ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+)")
|
endif()
|
||||||
set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}")
|
set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}")
|
||||||
string(APPEND ZLIB_VERSION_STRING ".${ZLIB_VERSION_TWEAK}")
|
set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}")
|
||||||
endif()
|
set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}")
|
||||||
|
set(ZLIB_VERSION "${ZLIB_VERSION_STRING}")
|
||||||
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()
|
endif()
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
|
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# CMake version number components.
|
# CMake version number components.
|
||||||
set(CMake_VERSION_MAJOR 3)
|
set(CMake_VERSION_MAJOR 3)
|
||||||
set(CMake_VERSION_MINOR 27)
|
set(CMake_VERSION_MINOR 27)
|
||||||
set(CMake_VERSION_PATCH 3)
|
set(CMake_VERSION_PATCH 4)
|
||||||
#set(CMake_VERSION_RC 0)
|
#set(CMake_VERSION_RC 0)
|
||||||
set(CMake_VERSION_IS_DIRTY 0)
|
set(CMake_VERSION_IS_DIRTY 0)
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ endif()
|
|||||||
|
|
||||||
if(NOT CMake_VERSION_NO_GIT)
|
if(NOT CMake_VERSION_NO_GIT)
|
||||||
# If this source was exported by 'git archive', use its commit info.
|
# 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.
|
# 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]* "
|
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]* "
|
||||||
|
@ -1360,7 +1360,9 @@ static const struct ListNode : public cmGeneratorExpressionNode
|
|||||||
try {
|
try {
|
||||||
auto list = GetList(args.front());
|
auto list = GetList(args.front());
|
||||||
args.advance(2);
|
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();
|
return list.to_string();
|
||||||
} catch (std::out_of_range& e) {
|
} catch (std::out_of_range& e) {
|
||||||
reportError(ctx, cnt->GetOriginalExpression(), e.what());
|
reportError(ctx, cnt->GetOriginalExpression(), e.what());
|
||||||
|
@ -740,9 +740,20 @@ public:
|
|||||||
// Throw std::out_of_range if index is invalid
|
// Throw std::out_of_range if index is invalid
|
||||||
template <typename InputIterator>
|
template <typename InputIterator>
|
||||||
cmList& insert_items(index_type index, InputIterator first,
|
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 <typename InputIterator>
|
||||||
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
cmList& insert_items(index_type index,
|
cmList& insert_items(index_type index,
|
||||||
|
@ -375,7 +375,8 @@ bool HandleInsertCommand(std::vector<std::string> const& args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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());
|
status.GetMakefile().AddDefinition(listName, list->to_string());
|
||||||
return true;
|
return true;
|
||||||
} catch (std::out_of_range& e) {
|
} catch (std::out_of_range& e) {
|
||||||
|
@ -161,3 +161,24 @@ foreach (_pol ${thelist})
|
|||||||
message(SEND_ERROR "returned element '${thevalue}', but expected '${_pol}'")
|
message(SEND_ERROR "returned element '${thevalue}', but expected '${_pol}'")
|
||||||
endif()
|
endif()
|
||||||
endforeach (_pol)
|
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()
|
||||||
|
@ -46,5 +46,52 @@ if (NOT output STREQUAL listvar)
|
|||||||
list (APPEND errors "returns bad value: ${output}")
|
list (APPEND errors "returns bad value: ${output}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
block(SCOPE_FOR POLICIES)
|
||||||
|
cmake_policy(SET CMP0007 NEW)
|
||||||
|
|
||||||
|
set(listvar "0;1;2;3;4")
|
||||||
|
list(INSERT listvar 1 "")
|
||||||
|
set (output "$<LIST:INSERT,0;1;2;3;4,1,>")
|
||||||
|
if (NOT output STREQUAL listvar)
|
||||||
|
list (APPEND errors "returns bad value: ${output}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(INSERT listvar 4 ";")
|
||||||
|
set (output "$<LIST:INSERT,0;;1;2;3;4,4,;>")
|
||||||
|
if (NOT output STREQUAL listvar)
|
||||||
|
list (APPEND errors "returns bad value: ${output}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(INSERT listvar 0 "x")
|
||||||
|
set (output "$<LIST:INSERT,0;;1;2;;;3;4,0,x>")
|
||||||
|
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 "$<LIST:INSERT,0;1;2;3;4,1,>")
|
||||||
|
if (NOT output STREQUAL listvar)
|
||||||
|
list (APPEND errors "returns bad value: ${output}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(INSERT listvar 4 ";")
|
||||||
|
set (output "$<LIST:INSERT,0;1;2;3;4,4,;>")
|
||||||
|
if (NOT output STREQUAL listvar)
|
||||||
|
list (APPEND errors "returns bad value: ${output}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(INSERT listvar 0 "x")
|
||||||
|
set (output "$<LIST:INSERT,0;1;2;3;4,0,x>")
|
||||||
|
if (NOT output STREQUAL listvar)
|
||||||
|
list (APPEND errors "returns bad value: ${output}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(CMAKE_WARN_DEPRECATED CACHE)
|
||||||
|
endblock()
|
||||||
|
|
||||||
check_errors("LIST:INSERT..." ${errors})
|
check_errors("LIST:INSERT..." ${errors})
|
||||||
|
@ -8,7 +8,7 @@ readonly name="cppdap"
|
|||||||
readonly ownership="cppdap Upstream <kwrobot@kitware.com>"
|
readonly ownership="cppdap Upstream <kwrobot@kitware.com>"
|
||||||
readonly subtree="Utilities/cmcppdap"
|
readonly subtree="Utilities/cmcppdap"
|
||||||
readonly repo="https://github.com/google/cppdap.git"
|
readonly repo="https://github.com/google/cppdap.git"
|
||||||
readonly tag="03cc18678ed2ed8b2424ec99dee7e4655d876db5" # 2023-05-25
|
readonly tag="cc2f2058846bb29e18fdadf455d5f5af71b2554f" # 2023-08-17
|
||||||
readonly shortlog=false
|
readonly shortlog=false
|
||||||
readonly paths="
|
readonly paths="
|
||||||
LICENSE
|
LICENSE
|
||||||
@ -23,6 +23,7 @@ extract_source () {
|
|||||||
echo "* -whitespace" > .gitattributes
|
echo "* -whitespace" > .gitattributes
|
||||||
fromdos LICENSE include/dap/* src/*
|
fromdos LICENSE include/dap/* src/*
|
||||||
echo "" >> LICENSE
|
echo "" >> LICENSE
|
||||||
|
echo "" >> src/content_stream.cpp
|
||||||
echo "" >> src/nlohmann_json_serializer.h
|
echo "" >> src/nlohmann_json_serializer.h
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,14 @@ ResponseOrError<T>& ResponseOrError<T>::operator=(ResponseOrError&& other) {
|
|||||||
// Session
|
// 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.
|
// Session implements a DAP client or server endpoint.
|
||||||
// The general usage is as follows:
|
// The general usage is as follows:
|
||||||
// (1) Create a session with Session::create().
|
// (1) Create a session with Session::create().
|
||||||
@ -144,6 +152,9 @@ class Session {
|
|||||||
// create() constructs and returns a new Session.
|
// create() constructs and returns a new Session.
|
||||||
static std::unique_ptr<Session> create();
|
static std::unique_ptr<Session> 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
|
// onError() registers a error handler that will be called whenever a protocol
|
||||||
// error is encountered.
|
// error is encountered.
|
||||||
// Only one error handler can be bound at any given time, and later calls
|
// Only one error handler can be bound at any given time, and later calls
|
||||||
|
@ -24,12 +24,15 @@ namespace dap {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// ContentReader
|
// ContentReader
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ContentReader::ContentReader(const std::shared_ptr<Reader>& reader)
|
ContentReader::ContentReader(
|
||||||
: reader(reader) {}
|
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 {
|
ContentReader& ContentReader::operator=(ContentReader&& rhs) noexcept {
|
||||||
buf = std::move(rhs.buf);
|
buf = std::move(rhs.buf);
|
||||||
reader = std::move(rhs.reader);
|
reader = std::move(rhs.reader);
|
||||||
|
on_invalid_data = std::move(rhs.on_invalid_data);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,17 +47,19 @@ void ContentReader::close() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string ContentReader::read() {
|
std::string ContentReader::read() {
|
||||||
matched_idx = 0;
|
|
||||||
|
|
||||||
// Find Content-Length header prefix
|
// Find Content-Length header prefix
|
||||||
if (!scan("Content-Length:")) {
|
if (on_invalid_data == kClose) {
|
||||||
return "";
|
if (!match("Content-Length:")) {
|
||||||
|
return badHeader();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!scan("Content-Length:")) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip whitespace and tabs
|
// Skip whitespace and tabs
|
||||||
while (matchAny(" \t")) {
|
while (matchAny(" \t")) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse length
|
// Parse length
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -68,20 +73,16 @@ std::string ContentReader::read() {
|
|||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expect \r\n\r\n
|
// Expect \r\n\r\n
|
||||||
if (!match("\r\n\r\n")) {
|
if (!match("\r\n\r\n")) {
|
||||||
return "";
|
return badHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read message
|
// Read message
|
||||||
if (!buffer(len + matched_idx)) {
|
if (!buffer(len)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < matched_idx; i++) {
|
|
||||||
buf.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string out;
|
std::string out;
|
||||||
out.reserve(len);
|
out.reserve(len);
|
||||||
for (size_t i = 0; i < len; i++) {
|
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) {
|
bool ContentReader::match(const uint8_t* seq, size_t len) {
|
||||||
if (!buffer(len + matched_idx)) {
|
if (!buffer(len)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto it = matched_idx;
|
auto it = buf.begin();
|
||||||
for (size_t i = 0; i < len; i++, it++) {
|
for (size_t i = 0; i < len; i++, it++) {
|
||||||
if (buf[it] != seq[i]) {
|
if (*it != seq[i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
matched_idx += len;
|
buf.pop_front();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,12 +129,12 @@ bool ContentReader::match(const char* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char ContentReader::matchAny(const char* chars) {
|
char ContentReader::matchAny(const char* chars) {
|
||||||
if (!buffer(1 + matched_idx)) {
|
if (!buffer(1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int c = buf[matched_idx];
|
int c = buf.front();
|
||||||
if (auto p = strchr(chars, c)) {
|
if (auto p = strchr(chars, c)) {
|
||||||
matched_idx++;
|
buf.pop_front();
|
||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -158,6 +160,13 @@ bool ContentReader::buffer(size_t bytes) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ContentReader::badHeader() {
|
||||||
|
if (on_invalid_data == kClose) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// ContentWriter
|
// ContentWriter
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "dap/session.h"
|
||||||
|
|
||||||
namespace dap {
|
namespace dap {
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
@ -30,7 +32,8 @@ class Writer;
|
|||||||
class ContentReader {
|
class ContentReader {
|
||||||
public:
|
public:
|
||||||
ContentReader() = default;
|
ContentReader() = default;
|
||||||
ContentReader(const std::shared_ptr<Reader>&);
|
ContentReader(const std::shared_ptr<Reader>&,
|
||||||
|
const OnInvalidData on_invalid_data = kIgnore);
|
||||||
ContentReader& operator=(ContentReader&&) noexcept;
|
ContentReader& operator=(ContentReader&&) noexcept;
|
||||||
|
|
||||||
bool isOpen();
|
bool isOpen();
|
||||||
@ -44,10 +47,11 @@ class ContentReader {
|
|||||||
bool match(const char* str);
|
bool match(const char* str);
|
||||||
char matchAny(const char* chars);
|
char matchAny(const char* chars);
|
||||||
bool buffer(size_t bytes);
|
bool buffer(size_t bytes);
|
||||||
|
std::string badHeader();
|
||||||
|
|
||||||
std::shared_ptr<Reader> reader;
|
std::shared_ptr<Reader> reader;
|
||||||
std::deque<uint8_t> buf;
|
std::deque<uint8_t> buf;
|
||||||
uint32_t matched_idx = 0;
|
OnInvalidData on_invalid_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContentWriter {
|
class ContentWriter {
|
||||||
|
@ -84,16 +84,43 @@ TEST(ContentStreamTest, ShortRead) {
|
|||||||
|
|
||||||
TEST(ContentStreamTest, PartialReadAndParse) {
|
TEST(ContentStreamTest, PartialReadAndParse) {
|
||||||
auto sb = std::make_shared<dap::StringBuffer>();
|
auto sb = std::make_shared<dap::StringBuffer>();
|
||||||
dap::ContentReader cs(sb);
|
|
||||||
sb->write("Content");
|
sb->write("Content");
|
||||||
ASSERT_EQ(cs.read(), "");
|
|
||||||
sb->write("-Length: ");
|
sb->write("-Length: ");
|
||||||
ASSERT_EQ(cs.read(), "");
|
|
||||||
sb->write("26");
|
sb->write("26");
|
||||||
ASSERT_EQ(cs.read(), "");
|
|
||||||
sb->write("\r\n\r\n");
|
sb->write("\r\n\r\n");
|
||||||
ASSERT_EQ(cs.read(), "");
|
|
||||||
sb->write("Content payload number one");
|
sb->write("Content payload number one");
|
||||||
|
|
||||||
|
dap::ContentReader cs(sb);
|
||||||
ASSERT_EQ(cs.read(), "Content payload number one");
|
ASSERT_EQ(cs.read(), "Content payload number one");
|
||||||
ASSERT_EQ(cs.read(), "");
|
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());
|
||||||
|
}
|
||||||
|
@ -35,6 +35,10 @@ namespace {
|
|||||||
|
|
||||||
class Impl : public dap::Session {
|
class Impl : public dap::Session {
|
||||||
public:
|
public:
|
||||||
|
void setOnInvalidData(dap::OnInvalidData onInvalidData_) override {
|
||||||
|
this->onInvalidData = onInvalidData_;
|
||||||
|
}
|
||||||
|
|
||||||
void onError(const ErrorHandler& handler) override { handlers.put(handler); }
|
void onError(const ErrorHandler& handler) override { handlers.put(handler); }
|
||||||
|
|
||||||
void registerHandler(const dap::TypeInfo* typeinfo,
|
void registerHandler(const dap::TypeInfo* typeinfo,
|
||||||
@ -69,7 +73,7 @@ class Impl : public dap::Session {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader = dap::ContentReader(r);
|
reader = dap::ContentReader(r, this->onInvalidData);
|
||||||
writer = dap::ContentWriter(w);
|
writer = dap::ContentWriter(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,6 +494,7 @@ class Impl : public dap::Session {
|
|||||||
dap::Chan<Payload> inbox;
|
dap::Chan<Payload> inbox;
|
||||||
std::atomic<uint32_t> nextSeq = {1};
|
std::atomic<uint32_t> nextSeq = {1};
|
||||||
std::mutex sendMutex;
|
std::mutex sendMutex;
|
||||||
|
dap::OnInvalidData onInvalidData = dap::kIgnore;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
@ -108,7 +108,6 @@ class dap::Socket::Shared : public dap::ReaderWriter {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(info);
|
|
||||||
term();
|
term();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -117,7 +116,9 @@ class dap::Socket::Shared : public dap::ReaderWriter {
|
|||||||
Shared(addrinfo* info, SOCKET socket) : info(info), s(socket) {}
|
Shared(addrinfo* info, SOCKET socket) : info(info), s(socket) {}
|
||||||
|
|
||||||
~Shared() {
|
~Shared() {
|
||||||
freeaddrinfo(info);
|
if (info) {
|
||||||
|
freeaddrinfo(info);
|
||||||
|
}
|
||||||
close();
|
close();
|
||||||
term();
|
term();
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
|
|
||||||
#include <algorithm> // std::min
|
#include <algorithm> // std::min
|
||||||
#include <cstring> // memcpy
|
#include <cstring> // memcpy
|
||||||
#include <memory> // std::unique_ptr
|
#include <deque>
|
||||||
|
#include <memory> // std::unique_ptr
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace dap {
|
namespace dap {
|
||||||
@ -39,6 +40,7 @@ class StringBuffer : public virtual Reader, public virtual Writer {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::string str;
|
std::string str;
|
||||||
|
std::deque<size_t> chunk_lengths;
|
||||||
bool closed = false;
|
bool closed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -62,12 +64,19 @@ std::string StringBuffer::string() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t StringBuffer::read(void* buffer, size_t bytes) {
|
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;
|
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);
|
memcpy(buffer, str.data(), len);
|
||||||
str = std::string(str.begin() + len, str.end());
|
str = std::string(str.begin() + len, str.end());
|
||||||
|
if (bytes < chunk_length) {
|
||||||
|
chunk_length -= bytes;
|
||||||
|
} else {
|
||||||
|
chunk_lengths.pop_front();
|
||||||
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +86,7 @@ bool StringBuffer::write(const void* buffer, size_t bytes) {
|
|||||||
}
|
}
|
||||||
auto chars = reinterpret_cast<const char*>(buffer);
|
auto chars = reinterpret_cast<const char*>(buffer);
|
||||||
str.append(chars, chars + bytes);
|
str.append(chars, chars + bytes);
|
||||||
|
chunk_lengths.push_back(bytes);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user