[llvm] [Windows] Avoid crash calling remove_directories() (PR #118677)

Dmitry Vasilyev via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 4 13:00:32 PST 2024


https://github.com/slydiman updated https://github.com/llvm/llvm-project/pull/118677

>From bc5973d214d1761c4a433f3f794bb7854d7d342b Mon Sep 17 00:00:00 2001
From: Dmitry Vasilyev <dvassiliev at accesssoftek.com>
Date: Wed, 4 Dec 2024 13:30:21 +0400
Subject: [PATCH 1/2] [Windows] Avoid crash calling remove_directories()

We faced an unexpected crash in SHELL32_CallFileCopyHooks() on the buildbot [lldb-remote-linux-win](https://lab.llvm.org/staging/#/builders/197/builds/1066).
The host is Windows Server 2022 w/o any 3rd party shell extensions.
See #118032 for more details.
Based on [this article](https://devblogs.microsoft.com/oldnewthing/20120330-00/?p=7963).
---
 llvm/lib/Support/Windows/Path.inc | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index c4bd5e24723517..ecea1efefe0098 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -1387,12 +1387,31 @@ std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
   Path16.push_back(0);
   Path16.push_back(0);
 
-  SHFILEOPSTRUCTW shfos = {};
-  shfos.wFunc = FO_DELETE;
-  shfos.pFrom = Path16.data();
-  shfos.fFlags = FOF_NO_UI;
+  HRESULT HR = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+  if (SUCCEEDED(HR)) {
+    IFileOperation *FileOp;
+    HR = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL,
+                          IID_PPV_ARGS(&FileOp));
+    if (SUCCEEDED(HR)) {
+      HR = FileOp->SetOperationFlags(FOF_NO_UI | FOFX_NOCOPYHOOKS);
+      if (SUCCEEDED(HR)) {
+        IShellItem *ShItem = NULL;
+        HR = SHCreateItemFromParsingName(Path16.data(), NULL,
+                                         IID_PPV_ARGS(&ShItem));
+        if (SUCCEEDED(HR)) {
+          HR = FileOp->DeleteItem(ShItem, NULL);
+          ShItem->Release();
+        }
+        if (SUCCEEDED(HR)) {
+          HR = FileOp->PerformOperations();
+        }
+      }
+      FileOp->Release();
+    }
+  }
+  CoUninitialize();
 
-  int result = ::SHFileOperationW(&shfos);
+  int result = FAILED(HR) ? HRESULT_CODE(HR) : 0;
   if (result != 0 && !IgnoreErrors)
     return mapWindowsError(result);
   return std::error_code();

>From 3fa927241bd1d5bc5ca97cd8578172426db040bb Mon Sep 17 00:00:00 2001
From: Dmitry Vasilyev <dvassiliev at accesssoftek.com>
Date: Thu, 5 Dec 2024 00:48:09 +0400
Subject: [PATCH 2/2] Updated with the behavior of SHFileOperationW().

---
 llvm/lib/Support/Windows/Path.inc | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index ecea1efefe0098..2daec202b227f8 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -1387,29 +1387,31 @@ std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
   Path16.push_back(0);
   Path16.push_back(0);
 
-  HRESULT HR = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+  HRESULT HR =
+      CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
   if (SUCCEEDED(HR)) {
-    IFileOperation *FileOp;
+    IFileOperation *FileOp = NULL;
     HR = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL,
                           IID_PPV_ARGS(&FileOp));
     if (SUCCEEDED(HR)) {
       HR = FileOp->SetOperationFlags(FOF_NO_UI | FOFX_NOCOPYHOOKS);
       if (SUCCEEDED(HR)) {
+        PIDLIST_ABSOLUTE PIDL = ILCreateFromPathW(Path16.data());
         IShellItem *ShItem = NULL;
-        HR = SHCreateItemFromParsingName(Path16.data(), NULL,
-                                         IID_PPV_ARGS(&ShItem));
+        HR = SHCreateItemFromIDList(PIDL, IID_PPV_ARGS(&ShItem));
         if (SUCCEEDED(HR)) {
           HR = FileOp->DeleteItem(ShItem, NULL);
+          if (SUCCEEDED(HR)) {
+            HR = FileOp->PerformOperations();
+          }
           ShItem->Release();
         }
-        if (SUCCEEDED(HR)) {
-          HR = FileOp->PerformOperations();
-        }
+        ILFree(PIDL);
       }
       FileOp->Release();
     }
+    CoUninitialize();
   }
-  CoUninitialize();
 
   int result = FAILED(HR) ? HRESULT_CODE(HR) : 0;
   if (result != 0 && !IgnoreErrors)



More information about the llvm-commits mailing list