Bug 1293501 - Use VirtualProtect to track down a possible memory corruption. r=dragana
authorTing-Yu Chou <janus926@gmail.com>
Thu, 06 Oct 2016 17:31:43 +0800
changeset 317398 2eebd44ff2e99123d3673ccacd0aa634d3cb4b85
parent 317397 ab0d0603172ee9da0246c15c023df9bab39b88b6
child 317399 73f5b0753f18b5a5345b0202f92988a0bb886d34
push id30804
push usercbook@mozilla.com
push dateTue, 11 Oct 2016 10:01:46 +0000
treeherdermozilla-central@7ae377917236 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana
bugs1293501
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1293501 - Use VirtualProtect to track down a possible memory corruption. r=dragana MozReview-Commit-ID: J4ZFzR1nE5n
netwerk/protocol/http/nsHttpHeaderArray.h
netwerk/protocol/http/nsHttpRequestHead.cpp
netwerk/protocol/http/nsHttpRequestHead.h
--- a/netwerk/protocol/http/nsHttpHeaderArray.h
+++ b/netwerk/protocol/http/nsHttpHeaderArray.h
@@ -105,33 +105,45 @@ public:
 
     uint32_t Count() const { return mHeaders.Length(); }
 
     const char *PeekHeaderAt(uint32_t i, nsHttpAtom &header) const;
 
     void Clear();
 
     // Must be copy-constructable and assignable
+#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
+#pragma pack(1)
+#endif
     struct nsEntry
     {
         nsHttpAtom header;
+#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
+        char padding[4096 -
+                     sizeof(nsTArrayHeader) -
+                     sizeof(nsHttpAtom) -
+                     sizeof(void*)];
+#endif
         nsCString value;
         HeaderVariety variety = eVarietyUnknown;
 
         struct MatchHeader {
           bool Equals(const nsEntry &aEntry, const nsHttpAtom &aHeader) const {
             return aEntry.header == aHeader;
           }
         };
 
         bool operator==(const nsEntry& aOther) const
         {
             return header == aOther.header && value == aOther.value;
         }
     };
+#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
+#pragma pack()
+#endif
 
     bool operator==(const nsHttpHeaderArray& aOther) const
     {
         return mHeaders == aOther.mHeaders;
     }
 
 private:
     // LookupEntry function will never return eVarietyResponseNetOriginal.
--- a/netwerk/protocol/http/nsHttpRequestHead.cpp
+++ b/netwerk/protocol/http/nsHttpRequestHead.cpp
@@ -11,29 +11,57 @@
 
 //-----------------------------------------------------------------------------
 // nsHttpRequestHead
 //-----------------------------------------------------------------------------
 
 namespace mozilla {
 namespace net {
 
+#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
+void nsHttpRequestHead::DbgReentrantMonitorAutoEnter::Protect(bool aOn)
+{
+    if (XRE_GetProcessType() == GeckoProcessType_Content &&
+        mInst.mHeaders.Count()) {
+        DWORD oldProtect;
+        LPVOID hdr = reinterpret_cast<PUINT8>(mInst.mHeaders.mHeaders.Elements()) -
+                     sizeof(nsTArrayHeader);
+        if (aOn) {
+            VirtualProtect(hdr, 4096, PAGE_READONLY, &oldProtect);
+        } else {
+            VirtualProtect(hdr, 4096, PAGE_READWRITE, &oldProtect);
+        }
+    }
+}
+
+#define ReentrantMonitorAutoEnter DbgReentrantMonitorAutoEnter
+#define mon(x) mon(*this)
+#endif
+
 nsHttpRequestHead::nsHttpRequestHead()
     : mMethod(NS_LITERAL_CSTRING("GET"))
     , mVersion(NS_HTTP_VERSION_1_1)
     , mParsedMethod(kMethod_Get)
     , mHTTPS(false)
     , mReentrantMonitor("nsHttpRequestHead.mReentrantMonitor")
     , mInVisitHeaders(false)
 {
     MOZ_COUNT_CTOR(nsHttpRequestHead);
 }
 
 nsHttpRequestHead::~nsHttpRequestHead()
 {
+#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
+    if (XRE_GetProcessType() == GeckoProcessType_Content && mHeaders.Count()) {
+        DWORD oldProtect;
+        LPVOID hdr = reinterpret_cast<PUINT8>(mHeaders.mHeaders.Elements()) -
+                     sizeof(nsTArrayHeader);
+        VirtualProtect(hdr, 4096, PAGE_READWRITE, &oldProtect);
+    }
+#endif
     MOZ_COUNT_DTOR(nsHttpRequestHead);
 }
 
 // Don't use this function. It is only used by HttpChannelParent to avoid
 // copying of request headers!!!
 const nsHttpHeaderArray &
 nsHttpRequestHead::Headers() const
 {
@@ -360,10 +388,15 @@ nsHttpRequestHead::Flatten(nsACString &b
         buf.AppendLiteral("1.0");
     }
 
     buf.AppendLiteral("\r\n");
 
     mHeaders.Flatten(buf, pruneProxyHeaders, false);
 }
 
+#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
+#undef ReentrantMonitorAutoEnter
+#undef mon
+#endif
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttpRequestHead.h
+++ b/netwerk/protocol/http/nsHttpRequestHead.h
@@ -115,14 +115,36 @@ private:
     bool              mHTTPS;
 
     // We are using ReentrantMonitor instead of a Mutex because VisitHeader
     // function calls nsIHttpHeaderVisitor::VisitHeader while under lock.
     ReentrantMonitor  mReentrantMonitor;
 
     // During VisitHeader we sould not allow cal to SetHeader.
     bool mInVisitHeaders;
+
+#if defined(XP_WIN) && (defined(_M_IX86) || defined(_M_X64))
+    class DbgReentrantMonitorAutoEnter : ReentrantMonitorAutoEnter
+    {
+    public:
+        explicit DbgReentrantMonitorAutoEnter(nsHttpRequestHead& aInst)
+            : ReentrantMonitorAutoEnter(aInst.mReentrantMonitor),
+              mInst(aInst)
+        {
+            Protect(false);
+        }
+        ~DbgReentrantMonitorAutoEnter(void)
+        {
+            Protect(true);
+        }
+
+    private:
+        void Protect(bool aOn);
+
+        nsHttpRequestHead& mInst;
+    };
+#endif
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // nsHttpRequestHead_h__