Bug 730051: Don't use SearchPathW to look for the DLL unless we're actually doing a load. r=bsmedberg
authorKyle Huey <khuey@kylehuey.com>
Thu, 01 Mar 2012 11:07:11 -0800
changeset 88252 3a7b9e61c26342f4fa46deb7f37cc6f6b389c00a
parent 88250 64c582d2b02c1127a8cdbdaeee27702bf7c221aa
child 88263 a48a08ecd5c16d4a148b9266b7f58fc7fa117f39
child 88330 f7a0d7946225016300945e05d6c92ee7e226efec
child 106320 f977d96263c2bbf35d4308c576feb7cce22c665e
push id157
push userMs2ger@gmail.com
push dateWed, 07 Mar 2012 19:27:10 +0000
reviewersbsmedberg
bugs730051
milestone13.0a1
Bug 730051: Don't use SearchPathW to look for the DLL unless we're actually doing a load. r=bsmedberg
toolkit/xre/nsWindowsDllBlocklist.cpp
--- a/toolkit/xre/nsWindowsDllBlocklist.cpp
+++ b/toolkit/xre/nsWindowsDllBlocklist.cpp
@@ -273,50 +273,54 @@ private:
 
   const char* mPreviousDllName;
   bool mReentered;
 };
 
 CRITICAL_SECTION ReentrancySentinel::sLock;
 std::map<DWORD, const char*>* ReentrancySentinel::sThreadMap;
 
+static
+wchar_t* getFullPath (PWCHAR filePath, wchar_t* fname)
+{
+  // In Windows 8, the first parameter seems to be used for more than just the
+  // path name.  For example, its numerical value can be 1.  Passing a non-valid
+  // pointer to SearchPathW will cause a crash, so we need to check to see if we
+  // are handed a valid pointer, and otherwise just pass NULL to SearchPathW.
+  PWCHAR sanitizedFilePath = (intptr_t(filePath) < 1024) ? NULL : filePath;
+
+  // figure out the length of the string that we need
+  DWORD pathlen = SearchPathW(sanitizedFilePath, fname, L".dll", 0, NULL, NULL);
+  if (pathlen == 0) {
+    return nsnull;
+  }
+
+  wchar_t* full_fname = new wchar_t[pathlen+1];
+  if (!full_fname) {
+    // couldn't allocate memory?
+    return nsnull;
+  }
+
+  // now actually grab it
+  SearchPathW(sanitizedFilePath, fname, L".dll", pathlen+1, full_fname, NULL);
+  return full_fname;
+}
+
 static NTSTATUS NTAPI
 patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
 {
   // We have UCS2 (UTF16?), we want ASCII, but we also just want the filename portion
 #define DLLNAME_MAX 128
   char dllName[DLLNAME_MAX+1];
   wchar_t *dll_part;
   DllBlockInfo *info;
 
   int len = moduleFileName->Length / 2;
   wchar_t *fname = moduleFileName->Buffer;
-
-  // In Windows 8, the first parameter seems to be used for more than just the
-  // path name.  For example, its numerical value can be 1.  Passing a non-valid
-  // pointer to SearchPathW will cause a crash, so we need to check to see if we
-  // are handed a valid pointer, and otherwise just pass NULL to SearchPathW.
-  PWCHAR sanitizedFilePath = (intptr_t(filePath) < 1024) ? NULL : filePath;
-
-  // figure out the length of the string that we need
-  DWORD pathlen = SearchPathW(sanitizedFilePath, fname, L".dll", 0, NULL, NULL);
-  if (pathlen == 0) {
-    // uh, we couldn't find the DLL at all, so...
-    printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
-    return STATUS_DLL_NOT_FOUND;
-  }
-
-  nsAutoArrayPtr<wchar_t> full_fname(new wchar_t[pathlen+1]);
-  if (!full_fname) {
-    // couldn't allocate memory?
-    return STATUS_DLL_NOT_FOUND;
-  }
-
-  // now actually grab it
-  SearchPathW(sanitizedFilePath, fname, L".dll", pathlen+1, full_fname, NULL);
+  nsAutoArrayPtr<wchar_t> full_fname;
 
   // The filename isn't guaranteed to be null terminated, but in practice
   // it always will be; ensure that this is so, and bail if not.
   // This is done instead of the more robust approach because of bug 527122,
   // where lots of weird things were happening when we tried to make a copy.
   if (moduleFileName->MaximumLength < moduleFileName->Length+2 ||
       fname[len] != 0)
   {
@@ -388,16 +392,23 @@ patched_LdrLoadDll (PWCHAR filePath, PUL
 #endif
 
     if (info->maxVersion != ALL_VERSIONS) {
       ReentrancySentinel sentinel(dllName);
       if (sentinel.BailOut()) {
         goto continue_loading;
       }
 
+      full_fname = getFullPath(filePath, fname);
+      if (!full_fname) {
+        // uh, we couldn't find the DLL at all, so...
+        printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
+        return STATUS_DLL_NOT_FOUND;
+      }
+
       DWORD zero;
       DWORD infoSize = GetFileVersionInfoSizeW(full_fname, &zero);
 
       // If we failed to get the version information, we block.
 
       if (infoSize != 0) {
         nsAutoArrayPtr<unsigned char> infoData(new unsigned char[infoSize]);
         VS_FIXEDFILEINFO *vInfo;
@@ -428,16 +439,23 @@ continue_loading:
 #ifdef DEBUG_very_verbose
   printf_stderr("LdrLoadDll: continuing load... ('%S')\n", moduleFileName->Buffer);
 #endif
 
   NS_SetHasLoadedNewDLLs();
 
   if (gInXPCOMLoadOnMainThread && NS_IsMainThread()) {
     // Check to ensure that the DLL has ASLR.
+    full_fname = getFullPath(filePath, fname);
+    if (!full_fname) {
+      // uh, we couldn't find the DLL at all, so...
+      printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
+      return STATUS_DLL_NOT_FOUND;
+    }
+
     if (!CheckASLR(full_fname)) {
       printf_stderr("LdrLoadDll: Blocking load of '%s'.  XPCOM components must support ASLR.\n", dllName);
       return STATUS_DLL_NOT_FOUND;
     }
   }
 
   return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
 }