diff options
author | Niall Douglas <s_github@nedprod.com> | 2022-09-13 20:12:48 +0300 |
---|---|---|
committer | Niall Douglas <s_github@nedprod.com> | 2022-09-13 20:12:48 +0300 |
commit | 05141b444da3ce26740fa0a22baac7f13704609e (patch) | |
tree | 8b26e5eb842dd17b54ad3a2ffea589a03af9839f | |
parent | ae7f9c5a92879285ad5100c89efc47ce1cb0031b (diff) |
Fix issue #102 Using a status code converted from a file_io_error segfaults.
-rw-r--r-- | cmake/tests.cmake | 1 | ||||
-rw-r--r-- | include/llfio/revision.hpp | 6 | ||||
-rw-r--r-- | include/llfio/v2.0/status_code.hpp | 40 | ||||
-rw-r--r-- | test/tests/issue0102.cpp | 45 | ||||
-rw-r--r-- | test/tests/tls_socket_handle.cpp | 9 |
5 files changed, 89 insertions, 12 deletions
diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 3a09d38c..630aeba3 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -19,6 +19,7 @@ set(llfio_TESTS "test/tests/issue0027.cpp" "test/tests/issue0028.cpp" "test/tests/issue0073.cpp" + "test/tests/issue0102.cpp" "test/tests/large_pages.cpp" "test/tests/map_handle_cache.cpp" "test/tests/map_handle_create_close/kernel_map_handle.cpp.hpp" diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp index c72ba4fd..f2b2549a 100644 --- a/include/llfio/revision.hpp +++ b/include/llfio/revision.hpp @@ -1,4 +1,4 @@ // Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time -#define LLFIO_PREVIOUS_COMMIT_REF 1714505e3cb9e9547bd45faaefcea1b9ad0506ae -#define LLFIO_PREVIOUS_COMMIT_DATE "2022-09-06 18:54:18 +00:00" -#define LLFIO_PREVIOUS_COMMIT_UNIQUE 1714505e +#define LLFIO_PREVIOUS_COMMIT_REF ae7f9c5a92879285ad5100c89efc47ce1cb0031b +#define LLFIO_PREVIOUS_COMMIT_DATE "2022-09-07 15:07:48 +00:00" +#define LLFIO_PREVIOUS_COMMIT_UNIQUE ae7f9c5a diff --git a/include/llfio/v2.0/status_code.hpp b/include/llfio/v2.0/status_code.hpp index eb1b2959..9813f4a1 100644 --- a/include/llfio/v2.0/status_code.hpp +++ b/include/llfio/v2.0/status_code.hpp @@ -194,8 +194,15 @@ public: static inline constexpr const file_io_error_domain &get(); #endif + virtual typename _base::payload_info_t payload_info() const noexcept override + { + return {sizeof(value_type), sizeof(SYSTEM_ERROR2_NAMESPACE::status_code_domain *) + sizeof(value_type), + (alignof(value_type) > alignof(SYSTEM_ERROR2_NAMESPACE::status_code_domain *)) ? alignof(value_type) : + alignof(SYSTEM_ERROR2_NAMESPACE::status_code_domain *)}; + } + protected: - virtual inline string_ref _do_message(const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override final + virtual inline string_ref _do_message(const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override { assert(code.domain() == *this); const auto &v = static_cast<const SYSTEM_ERROR2_NAMESPACE::status_code<file_io_error_domain> &>(code); // NOLINT @@ -246,6 +253,27 @@ protected: memcpy(p, ret.c_str(), ret.size() + 1); return atomic_refcounted_string_ref(p, ret.size()); } + virtual bool _do_erased_copy(SYSTEM_ERROR2_NAMESPACE::status_code<void> &dst, const SYSTEM_ERROR2_NAMESPACE::status_code<void> &src, + typename _base::payload_info_t dstinfo) const override + { + // Note that dst may not have its domain set + const auto srcinfo = payload_info(); + if(dstinfo.total_size >= srcinfo.total_size) + { + // Identity + memcpy(&dst, &src, srcinfo.total_size); + return true; + } + if(dstinfo.total_size >= sizeof(SYSTEM_ERROR2_NAMESPACE::status_code_domain *) + sizeof(value_type::sc)) + { + // Allow dropping LLFIO additional state + const auto *basedomain = &_base::get(); + memcpy(&dst, &src, sizeof(SYSTEM_ERROR2_NAMESPACE::status_code_domain *) + sizeof(value_type::sc)); + memcpy(&dst, &basedomain, sizeof(SYSTEM_ERROR2_NAMESPACE::status_code_domain *)); + return true; + } + return false; + } }; #if __cplusplus >= 201402L || defined(_MSC_VER) template <class BaseStatusCodeDomain> constexpr file_io_error_domain<BaseStatusCodeDomain> file_io_error_domain_inst = {}; @@ -327,7 +355,10 @@ inline file_io_error ntkernel_error(SYSTEM_ERROR2_NAMESPACE::win32::NTSTATUS c); namespace detail { - inline std::ostream &operator<<(std::ostream &s, const file_io_error &v) { return s << "llfio::file_io_error(" << v.message().c_str() << ")"; } + inline std::ostream &operator<<(std::ostream &s, const file_io_error &v) + { + return s << "llfio::file_io_error(" << v.message().c_str() << ")"; + } } // namespace detail inline file_io_error error_from_exception(std::exception_ptr &&ep = std::current_exception(), SYSTEM_ERROR2_NAMESPACE::system_code not_matched = errc::resource_unavailable_try_again) noexcept @@ -408,7 +439,10 @@ public: } //! Retrieve the value of the error code - int value() const noexcept { return ec.value(); } + int value() const noexcept + { + return ec.value(); + } //! Retrieve any first path associated with this failure. Note this only works if called from the same thread as where the failure occurred. inline filesystem::path path1() const { diff --git a/test/tests/issue0102.cpp b/test/tests/issue0102.cpp new file mode 100644 index 00000000..6ba76e62 --- /dev/null +++ b/test/tests/issue0102.cpp @@ -0,0 +1,45 @@ +/* Integration test kernel for issue #73 Windows directory junctions cannot be opened with symlink_handle +(C) 2022 Niall Douglas <http://www.nedproductions.biz/> (2 commits) +File Created: Sept 2022 + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License in the accompanying file +Licence.txt or at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +Distributed under the Boost Software License, Version 1.0. + (See accompanying file Licence.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +#include "../test_kernel_decl.hpp" + +static inline void TestIssue0102() +{ + namespace llfio = LLFIO_V2_NAMESPACE; + namespace outcome_e = OUTCOME_V2_NAMESPACE::experimental; + + auto page = llfio::utils::page_allocator<std::byte>().allocate(llfio::utils::page_size()); + + llfio::file_io_error ioError = llfio::generic_error(llfio::errc::state_not_recoverable); + + // (I know this is very likely to be misaligned on 64Bit systems, but + // otherwise the problem/segfault is only triggered on 32Bit systems) + auto erasedError = + new(page + llfio::utils::page_size() - sizeof(outcome_e::status_code_domain *) - sizeof(int)) outcome_e::errored_status_code<outcome_e::erased<int>>(ioError); + + // the following line must not segfault + std::cout << erasedError->message() << std::endl; +} + +KERNELTEST_TEST_KERNEL(regression, llfio, issues, 0102, "Tests issue #0102 Using a status code converted from a file_io_error segfaults", TestIssue0102()) diff --git a/test/tests/tls_socket_handle.cpp b/test/tests/tls_socket_handle.cpp index 5df7dd3d..631c3023 100644 --- a/test/tests/tls_socket_handle.cpp +++ b/test/tests/tls_socket_handle.cpp @@ -285,10 +285,7 @@ static inline void TestAuthenticatingTLSSocketHandles() //! [https_get] namespace llfio = LLFIO_V2_NAMESPACE; static constexpr llfio::string_view test_host("github.com"); - static constexpr llfio::string_view get_request(R"(GET / HTTP/1.0 -Host: github.com - -)"); + static constexpr llfio::string_view get_request("GET / HTTP/1.0\r\nHost: github.com\r\n\r\n"); if(llfio::tls_socket_source_registry::empty()) { std::cout << "\nNOTE: This platform has no TLS socket sources in its registry, skipping this test." << std::endl; @@ -320,9 +317,9 @@ Host: github.com // Fetch the front page. The connection will close once all data is sent. std::vector<llfio::byte> buffer(4096); size_t offset = 0; - for(size_t readed = 0; (readed = sock->read({{buffer.data() + offset, buffer.size() - offset}}, std::chrono::seconds(3)).value()) > 0;) + for(size_t nread = 0; (nread = sock->read({{buffer.data() + offset, buffer.size() - offset}}, std::chrono::seconds(3)).value()) > 0;) { - offset += readed; + offset += nread; if(buffer.size() - offset < 1024) { buffer.resize(buffer.size() + 4096); |