Преглед изворни кода

Merge topic 'filesystem-path-c++03-abi'

ee9805ccd1 cm/filesystem: Fix crash with pre-C++11 std::string GNU ABI in C++17

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !7813
Brad King пре 3 година
родитељ
комит
7c71f9b1e8
3 измењених фајлова са 18 додато и 13 уклоњено
  1. 1 3
      Source/Checks/cm_cxx_features.cmake
  2. 11 0
      Source/Checks/cm_cxx_filesystem.cxx
  3. 6 10
      Utilities/std/cm/filesystem

+ 1 - 3
Source/Checks/cm_cxx_features.cmake

@@ -80,9 +80,7 @@ if(CMake_HAVE_CXX_MAKE_UNIQUE)
   set(CMake_HAVE_CXX_UNIQUE_PTR 1)
 endif()
 cm_check_cxx_feature(unique_ptr)
-if (NOT CMAKE_CXX_STANDARD LESS "17"
-    AND NOT MSYS # FIXME: RunCMake.cmake_path cases crash with MSYS std::filesystem
-    )
+if (NOT CMAKE_CXX_STANDARD LESS "17")
   if (NOT CMAKE_CROSSCOMPILING OR CMAKE_CROSSCOMPILING_EMULATOR)
     cm_check_cxx_feature(filesystem TRY_RUN)
   else()

+ 11 - 0
Source/Checks/cm_cxx_filesystem.cxx

@@ -23,5 +23,16 @@ int main()
   }
 #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;
 }

+ 6 - 10
Utilities/std/cm/filesystem

@@ -809,13 +809,11 @@ public:
 
   path& remove_filename()
   {
-#  if defined(__CYGWIN__)
-    // FIXME: Avoid crash due to CYGWIN/MSYS bug(?).  See CMake Issue 22090.
-    static_cast<void>(this->path_.data());
-#  endif
     auto fname = this->get_filename();
     if (!fname.empty()) {
-      this->path_.erase(fname.data() - this->path_.data());
+      this->path_.erase(fname.data() -
+                        // Avoid C++17 non-const .data() that may reallocate.
+                        static_cast<path_type const&>(this->path_).data());
     }
     return *this;
   }
@@ -829,13 +827,11 @@ public:
 
   path& replace_extension(const path& replacement = path())
   {
-#  if defined(__CYGWIN__)
-    // FIXME: Avoid crash due to CYGWIN/MSYS bug(?).  See CMake Issue 22090.
-    static_cast<void>(this->path_.data());
-#  endif
     auto ext = this->get_filename_fragment(filename_fragment::extension);
     if (!ext.empty()) {
-      this->path_.erase(ext.data() - this->path_.data());
+      this->path_.erase(ext.data() -
+                        // Avoid C++17 non-const .data() that may reallocate.
+                        static_cast<path_type const&>(this->path_).data());
     }
     if (!replacement.path_.empty()) {
       if (replacement.path_[0] != '.') {