mirror of
https://github.com/Kitware/CMake.git
synced 2025-06-15 08:30:44 +08:00

The `remove_filename` and `replace_extension` methods compute an offset between the whole path in a `std::string` and a part of a path in a `std::string_view`. This is done by subtracting their `.data()` pointers. However, C++17 adds a non-const `.data()` through which modification of the string is allowed. This means the copy-on-write implementation used by the pre-C++11 std::string GNU ABI must reallocate if the string has been copied. Our subtraction then computes an offset between two different allocations, which is undefined behavior. The workaround in commit b3ca4f9ad1 (cm/filesystem: Work around crash when compiled for CYGWIN/MSYS runtime, 2021-04-22, v3.21.0-rc1~271^2~2) avoided the problem by calling the non-const `.data()` to reallocate before constructing the `string_view`. Instead, explicitly call the const `.data()` method on the string, which does not reallocate. Fixes: #22090, #23328
39 lines
985 B
C++
39 lines
985 B
C++
|
|
#include <filesystem>
|
|
|
|
int main()
|
|
{
|
|
std::filesystem::path p0(L"/a/b/c");
|
|
|
|
std::filesystem::path p1("/a/b/c");
|
|
std::filesystem::path p2("/a/b/c");
|
|
if (p1 != p2) {
|
|
return 1;
|
|
}
|
|
|
|
#if defined(_WIN32)
|
|
std::filesystem::path p3("//host/a/b/../c");
|
|
if (p3.lexically_normal().generic_string() != "//host/a/c") {
|
|
return 1;
|
|
}
|
|
|
|
std::filesystem::path p4("c://a/.///b/../");
|
|
if (p4.lexically_normal().generic_string() != "c:/a/") {
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
// If std::string is copy-on-write, the std::filesystem::path
|
|
// implementation may accidentally trigger a reallocation and compute
|
|
// an offset between two allocations, leading to undefined behavior.
|
|
#if defined(__GLIBCXX__) && \
|
|
(!defined(_GLIBCXX_USE_CXX11_ABI) || !_GLIBCXX_USE_CXX11_ABI)
|
|
std::string p5s1 = "/path";
|
|
std::string p5s2 = std::move(p5s1);
|
|
std::filesystem::path p5 = std::string(p5s2);
|
|
p5.remove_filename();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|