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 423601 2eebd44ff2e99123d3673ccacd0aa634d3cb4b85
parent 423600 ab0d0603172ee9da0246c15c023df9bab39b88b6
child 423602 73f5b0753f18b5a5345b0202f92988a0bb886d34
push id31945
push users.kaspari@gmail.com
push dateTue, 11 Oct 2016 12:27:19 +0000
reviewersdragana
bugs1293501
milestone52.0a1
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__