Bug 1023239 - Block crashy builds of V-Bates. r=bsmedberg, a=sledru
authorDavid Major <dmajor@mozilla.com>
Tue, 01 Jul 2014 09:33:43 +1200
changeset 207581 8a2ea552dfd1d45928fcf3b45242db3d9812745f
parent 207580 234b0fa642adfc692e09919e80b64d4e4aecd7e5
child 207582 90bfb178a10a53cd972c73ca627e424c9c042c19
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, sledru
bugs1023239
milestone32.0a2
Bug 1023239 - Block crashy builds of V-Bates. r=bsmedberg, a=sledru
mozglue/build/WindowsDllBlocklist.cpp
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -42,22 +42,26 @@ struct DllBlockInfo {
   // If maxVersion is ALL_VERSIONS, we'll block all versions of this
   // dll.  Otherwise, we'll block all versions less than or equal to
   // the given version, as queried by GetFileVersionInfo and
   // VS_FIXEDFILEINFO's dwFileVersionMS and dwFileVersionLS fields.
   //
   // Note that the version is usually 4 components, which is A.B.C.D
   // encoded as 0x AAAA BBBB CCCC DDDD ULL (spaces added for clarity),
   // but it's not required to be of that format.
+  //
+  // If the USE_TIMESTAMP flag is set, then we use the timestamp from
+  // the IMAGE_FILE_HEADER in lieu of a version number.
   unsigned long long maxVersion;
 
   enum {
     FLAGS_DEFAULT = 0,
     BLOCK_WIN8PLUS_ONLY = 1,
-    BLOCK_XP_ONLY = 2
+    BLOCK_XP_ONLY = 2,
+    USE_TIMESTAMP = 4,
   } flags;
 };
 
 static DllBlockInfo sWindowsDllBlocklist[] = {
   // EXAMPLE:
   // { "uxtheme.dll", ALL_VERSIONS },
   // { "uxtheme.dll", 0x0000123400000000ULL },
   // The DLL name must be in lowercase!
@@ -139,18 +143,20 @@ static DllBlockInfo sWindowsDllBlocklist
   { "atkdx11disp.dll", ALL_VERSIONS },
 
   // Topcrash with Conduit SearchProtect, bug 944542
   { "spvc32.dll", ALL_VERSIONS },
 
   // XP topcrash with F-Secure, bug 970362
   { "fs_ccf_ni_umh32.dll", MAKE_VERSION(1, 42, 101, 0), DllBlockInfo::BLOCK_XP_ONLY },
 
-  // Topcrash with V-bates, bug 1002748
+  // Topcrash with V-bates, bug 1002748 and bug 1023239
   { "libinject.dll", UNVERSIONED },
+  { "libinject2.dll", 0x537DDC93, DllBlockInfo::USE_TIMESTAMP },
+  { "libredir2.dll", 0x5385B7ED, DllBlockInfo::USE_TIMESTAMP },
 
   // Crashes with RoboForm2Go written against old SDK, bug 988311
   { "rf-firefox-22.dll", ALL_VERSIONS },
 
   { nullptr, 0 }
 };
 
 #ifndef STATUS_DLL_NOT_FOUND
@@ -267,16 +273,43 @@ CheckASLR(const wchar_t* path)
       ::CloseHandle(map);
     }
     ::CloseHandle(file);
   }
 
   return retval;
 }
 
+DWORD
+GetTimestamp(const wchar_t* path)
+{
+  DWORD timestamp = 0;
+
+  HANDLE file = ::CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
+                              nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+                              nullptr);
+  if (file != INVALID_HANDLE_VALUE) {
+    HANDLE map = ::CreateFileMappingW(file, nullptr, PAGE_READONLY, 0, 0,
+                                      nullptr);
+    if (map) {
+      RVAMap<IMAGE_DOS_HEADER> peHeader(map, 0);
+      if (peHeader) {
+        RVAMap<IMAGE_NT_HEADERS> ntHeader(map, peHeader->e_lfanew);
+        if (ntHeader) {
+          timestamp = ntHeader->FileHeader.TimeDateStamp;
+        }
+      }
+      ::CloseHandle(map);
+    }
+    ::CloseHandle(file);
+  }
+
+  return timestamp;
+}
+
 // This lock protects both the reentrancy sentinel and the crash reporter
 // data structures.
 static CRITICAL_SECTION sLock;
 
 /**
  * Some versions of Windows call LoadLibraryEx to get the version information
  * for a DLL, which causes our patched LdrLoadDll implementation to re-enter
  * itself and cause infinite recursion and a stack-exhaustion crash. We protect
@@ -566,37 +599,44 @@ patched_LdrLoadDll (PWCHAR filePath, PUL
 
       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 (info->flags & DllBlockInfo::USE_TIMESTAMP) {
+        fVersion = GetTimestamp(full_fname);
+        if (fVersion > info->maxVersion) {
+          load_ok = true;
+        }
+      } else {
+        DWORD zero;
+        DWORD infoSize = GetFileVersionInfoSizeW(full_fname, &zero);
 
-      if (infoSize != 0) {
-        nsAutoArrayPtr<unsigned char> infoData(new unsigned char[infoSize]);
-        VS_FIXEDFILEINFO *vInfo;
-        UINT vInfoLen;
+        // If we failed to get the version information, we block.
 
-        if (GetFileVersionInfoW(full_fname, 0, infoSize, infoData) &&
-            VerQueryValueW(infoData, L"\\", (LPVOID*) &vInfo, &vInfoLen))
-        {
-          fVersion =
-            ((unsigned long long)vInfo->dwFileVersionMS) << 32 |
-            ((unsigned long long)vInfo->dwFileVersionLS);
+        if (infoSize != 0) {
+          nsAutoArrayPtr<unsigned char> infoData(new unsigned char[infoSize]);
+          VS_FIXEDFILEINFO *vInfo;
+          UINT vInfoLen;
 
-          // finally do the version check, and if it's greater than our block
-          // version, keep loading
-          if (fVersion > info->maxVersion)
-            load_ok = true;
+          if (GetFileVersionInfoW(full_fname, 0, infoSize, infoData) &&
+              VerQueryValueW(infoData, L"\\", (LPVOID*) &vInfo, &vInfoLen))
+          {
+            fVersion =
+              ((unsigned long long)vInfo->dwFileVersionMS) << 32 |
+              ((unsigned long long)vInfo->dwFileVersionLS);
+
+            // finally do the version check, and if it's greater than our block
+            // version, keep loading
+            if (fVersion > info->maxVersion)
+              load_ok = true;
+          }
         }
       }
     }
 
     if (!load_ok) {
       printf_stderr("LdrLoadDll: Blocking load of '%s' -- see http://www.mozilla.com/en-US/blocklist/\n", dllName);
       DllBlockSet::Add(info->name, fVersion);
       return STATUS_DLL_NOT_FOUND;