summary refs log tree commit diff
path: root/gnu
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2016-03-10 02:57:05 -0500
committerMark H Weaver <mhw@netris.org>2016-03-10 10:52:41 -0500
commitc3499ad6b8cfdf1c6b09aa51f9f681a5be6c8962 (patch)
tree5013ce433bb697afc6086c4c4b1532cf57ea8bd5 /gnu
parentec278439f3ff5dcd3d02c05099ba1724cc2459f1 (diff)
downloadguix-c3499ad6b8cfdf1c6b09aa51f9f681a5be6c8962.tar.gz
gnu: icecat: Add several security fixes.
* gnu/packages/patches/icecat-CVE-2015-4477.patch,
gnu/packages/patches/icecat-CVE-2015-7207.patch,
gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch,
gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch,
gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch,
gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch,
gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch,
gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch,
gnu/packages/patches/icecat-CVE-2016-1954.patch,
gnu/packages/patches/icecat-CVE-2016-1960.patch,
gnu/packages/patches/icecat-CVE-2016-1961.patch,
gnu/packages/patches/icecat-CVE-2016-1962.patch,
gnu/packages/patches/icecat-CVE-2016-1964.patch,
gnu/packages/patches/icecat-CVE-2016-1965.patch,
gnu/packages/patches/icecat-CVE-2016-1966.patch,
gnu/packages/patches/icecat-CVE-2016-1974.patch,
gnu/packages/patches/icecat-bug-1248851.patch: New files.
* gnu-system.am (dist_patch_DATA): Add them.
* gnu/packages/gnuzilla.scm (icecat)[source]: Add patches.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/packages/gnuzilla.scm19
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-4477.patch37
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-7207.patch1140
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch356
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch58
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch60
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch53
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch32
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch103
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1954.patch32
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1960.patch55
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1961.patch33
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1962.patch107
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1964.patch54
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1965.patch44
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1966.patch36
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1974.patch530
-rw-r--r--gnu/packages/patches/icecat-bug-1248851.patch37
18 files changed, 2785 insertions, 1 deletions
diff --git a/gnu/packages/gnuzilla.scm b/gnu/packages/gnuzilla.scm
index 1a2057a343..b4892d77cd 100644
--- a/gnu/packages/gnuzilla.scm
+++ b/gnu/packages/gnuzilla.scm
@@ -291,7 +291,24 @@ standards.")
                     '("icecat-avoid-bundled-includes.patch"
                       "icecat-re-enable-DHE-cipher-suites.patch"
                       "icecat-update-graphite2.patch"
-                      "icecat-update-graphite2-pt2.patch")))
+                      "icecat-update-graphite2-pt2.patch"
+                      "icecat-CVE-2015-4477.patch"
+                      "icecat-CVE-2015-7207.patch"
+                      "icecat-CVE-2016-1952-pt01.patch"
+                      "icecat-CVE-2016-1952-pt02.patch"
+                      "icecat-CVE-2016-1952-pt03.patch"
+                      "icecat-CVE-2016-1952-pt04.patch"
+                      "icecat-CVE-2016-1952-pt05.patch"
+                      "icecat-CVE-2016-1952-pt06.patch"
+                      "icecat-CVE-2016-1954.patch"
+                      "icecat-CVE-2016-1960.patch"
+                      "icecat-CVE-2016-1961.patch"
+                      "icecat-CVE-2016-1962.patch"
+                      "icecat-CVE-2016-1964.patch"
+                      "icecat-CVE-2016-1965.patch"
+                      "icecat-CVE-2016-1966.patch"
+                      "icecat-CVE-2016-1974.patch"
+                      "icecat-bug-1248851.patch")))
       (modules '((guix build utils)))
       (snippet
        '(begin
diff --git a/gnu/packages/patches/icecat-CVE-2015-4477.patch b/gnu/packages/patches/icecat-CVE-2015-4477.patch
new file mode 100644
index 0000000000..c010c5ecec
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-4477.patch
@@ -0,0 +1,37 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/beae8783b8c2
+
+# HG changeset patch
+# User Paul Adenot <paul@paul.cx>
+# Date 1456422965 0
+# Node ID beae8783b8c2c672da12a95c70ae663cbd0d5016
+# Parent  3a606f8182c82480f8f350b622ab55a170ec1eb6
+Bug 1179484. r=roc
+
+MozReview-Commit-ID: HNaYLyMe3sM
+
+diff --git a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
+--- a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
++++ b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
+@@ -69,16 +69,20 @@ MediaStreamAudioDestinationNode::MediaSt
+               ChannelInterpretation::Speakers)
+   , mDOMStream(DOMAudioNodeMediaStream::CreateTrackUnionStream(GetOwner(),
+                                                                this))
+ {
+   TrackUnionStream* tus = static_cast<TrackUnionStream*>(mDOMStream->GetStream());
+   MOZ_ASSERT(tus == mDOMStream->GetStream()->AsProcessedStream());
+   tus->SetTrackIDFilter(FilterAudioNodeStreamTrack);
+ 
++  if (aContext->Graph() != tus->Graph()) {
++    return;
++  }
++
+   MediaStreamDestinationEngine* engine = new MediaStreamDestinationEngine(this, tus);
+   mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
+   mPort = tus->AllocateInputPort(mStream, 0);
+ 
+   nsIDocument* doc = aContext->GetParentObject()->GetExtantDoc();
+   if (doc) {
+     mDOMStream->CombineWithPrincipal(doc->NodePrincipal());
+   }
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-7207.patch b/gnu/packages/patches/icecat-CVE-2015-7207.patch
new file mode 100644
index 0000000000..db5fc6ce66
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-7207.patch
@@ -0,0 +1,1140 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/532544c91db7
+
+# HG changeset patch
+# User Dragana Damjanovic <dd.mozilla@gmail.com>
+# Date 1456962626 28800
+# Node ID 532544c91db7f13c39be1b7b7c4461cd03126e9c
+# Parent  f4220254d5bd0851a439467da39ba431e0ce2804
+Bug 1185256 - Save originURI to the history. r=bz ba=ritu
+
+MozReview-Commit-ID: Lvh9C84RQUc
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -1020,16 +1020,17 @@ nsDocShell::DestroyChildren()
+ //*****************************************************************************
+ // nsDocShell::nsISupports
+ //*****************************************************************************
+ 
+ NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
+ NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
+ 
+ NS_INTERFACE_MAP_BEGIN(nsDocShell)
++  NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38_2)
+   NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38)
+   NS_INTERFACE_MAP_ENTRY(nsIDocShell)
+   NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
+   NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
+   NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
+   NS_INTERFACE_MAP_ENTRY(nsIScrollable)
+   NS_INTERFACE_MAP_ENTRY(nsITextScroll)
+   NS_INTERFACE_MAP_ENTRY(nsIDocCharset)
+@@ -1372,16 +1373,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
+     return NS_OK; // JS may not handle returning of an error code
+   }
+ 
+   if (DoAppRedirectIfNeeded(aURI, aLoadInfo, aFirstParty)) {
+     return NS_OK;
+   }
+ 
+   nsCOMPtr<nsIURI> referrer;
++  nsCOMPtr<nsIURI> originalURI;
+   nsCOMPtr<nsIInputStream> postStream;
+   nsCOMPtr<nsIInputStream> headersStream;
+   nsCOMPtr<nsISupports> owner;
+   bool inheritOwner = false;
+   bool ownerIsExplicit = false;
+   bool sendReferrer = true;
+   uint32_t referrerPolicy = mozilla::net::RP_Default;
+   bool isSrcdoc = false;
+@@ -1398,16 +1400,20 @@ nsDocShell::LoadURI(nsIURI* aURI,
+   if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
+       mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
+     StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
+   }
+ 
+   // Extract the info from the DocShellLoadInfo struct...
+   if (aLoadInfo) {
+     aLoadInfo->GetReferrer(getter_AddRefs(referrer));
++    nsCOMPtr<nsIDocShellLoadInfo_ESR38> liESR38 = do_QueryInterface(aLoadInfo);
++    if (liESR38) {
++      liESR38->GetOriginalURI(getter_AddRefs(originalURI));
++    }
+ 
+     nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
+     aLoadInfo->GetLoadType(&lt);
+     // Get the appropriate loadType from nsIDocShellLoadInfo type
+     loadType = ConvertDocShellLoadInfoToLoadType(lt);
+ 
+     aLoadInfo->GetOwner(getter_AddRefs(owner));
+     aLoadInfo->GetInheritOwner(&inheritOwner);
+@@ -1652,34 +1658,35 @@ nsDocShell::LoadURI(nsIURI* aURI,
+   if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
+     flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
+   }
+ 
+   if (isSrcdoc) {
+     flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
+   }
+ 
+-  return InternalLoad(aURI,
+-                      referrer,
+-                      referrerPolicy,
+-                      owner,
+-                      flags,
+-                      target.get(),
+-                      nullptr,      // No type hint
+-                      NullString(), // No forced download
+-                      postStream,
+-                      headersStream,
+-                      loadType,
+-                      nullptr, // No SHEntry
+-                      aFirstParty,
+-                      srcdoc,
+-                      sourceDocShell,
+-                      baseURI,
+-                      nullptr,  // No nsIDocShell
+-                      nullptr); // No nsIRequest
++  return InternalLoad2(aURI,
++                       originalURI,
++                       referrer,
++                       referrerPolicy,
++                       owner,
++                       flags,
++                       target.get(),
++                       nullptr,      // No type hint
++                       NullString(), // No forced download
++                       postStream,
++                       headersStream,
++                       loadType,
++                       nullptr, // No SHEntry
++                       aFirstParty,
++                       srcdoc,
++                       sourceDocShell,
++                       baseURI,
++                       nullptr,  // No nsIDocShell
++                       nullptr); // No nsIRequest
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
+                        const nsACString& aContentType,
+                        const nsACString& aContentCharset,
+                        nsIDocShellLoadInfo* aLoadInfo)
+ {
+@@ -5398,21 +5405,21 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
+   // end of the URL, so append it last.
+   errorPageUrl.AppendLiteral("&d=");
+   errorPageUrl.AppendASCII(escapedDescription.get());
+ 
+   nsCOMPtr<nsIURI> errorPageURI;
+   rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
+   NS_ENSURE_SUCCESS(rv, rv);
+ 
+-  return InternalLoad(errorPageURI, nullptr, mozilla::net::RP_Default,
+-                      nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr,
+-                      nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
+-                      nullptr, true, NullString(), this, nullptr, nullptr,
+-                      nullptr);
++  return InternalLoad2(errorPageURI, nullptr, nullptr, mozilla::net::RP_Default,
++                       nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr,
++                       nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
++                       nullptr, true, NullString(), this, nullptr, nullptr,
++                       nullptr);
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::Reload(uint32_t aReloadFlags)
+ {
+   if (!IsNavigationAllowed()) {
+     return NS_OK; // JS may not handle returning of an error code
+   }
+@@ -5448,44 +5455,54 @@ nsDocShell::Reload(uint32_t aReloadFlags
+     nsCOMPtr<nsIDocument> doc(GetDocument());
+ 
+     // Do not inherit owner from document
+     uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
+     nsAutoString srcdoc;
+     nsIPrincipal* principal = nullptr;
+     nsAutoString contentTypeHint;
+     nsCOMPtr<nsIURI> baseURI;
++    nsCOMPtr<nsIURI> originalURI;
+     if (doc) {
+       principal = doc->NodePrincipal();
+       doc->GetContentType(contentTypeHint);
+ 
+       if (doc->IsSrcdocDocument()) {
+         doc->GetSrcdocData(srcdoc);
+         flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
+         baseURI = doc->GetBaseURI();
+       }
+-    }
+-    rv = InternalLoad(mCurrentURI,
+-                      mReferrerURI,
+-                      mReferrerPolicy,
+-                      principal,
+-                      flags,
+-                      nullptr,         // No window target
+-                      NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
+-                      NullString(),    // No forced download
+-                      nullptr,         // No post data
+-                      nullptr,         // No headers data
+-                      loadType,        // Load type
+-                      nullptr,         // No SHEntry
+-                      true,
+-                      srcdoc,          // srcdoc argument for iframe
+-                      this,            // For reloads we are the source
+-                      baseURI,
+-                      nullptr,         // No nsIDocShell
+-                      nullptr);        // No nsIRequest
++      nsCOMPtr<nsIChannel> chan = doc->GetChannel();
++      if (chan) {
++        nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
++        if (httpChan) {
++          httpChan->GetOriginalURI(getter_AddRefs(originalURI));
++        }
++      } 
++    }
++
++    rv = InternalLoad2(mCurrentURI,
++                       originalURI,
++                       mReferrerURI,
++                       mReferrerPolicy,
++                       principal,
++                       flags,
++                       nullptr,         // No window target
++                       NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
++                       NullString(),    // No forced download
++                       nullptr,         // No post data
++                       nullptr,         // No headers data
++                       loadType,        // Load type
++                       nullptr,         // No SHEntry
++                       true,
++                       srcdoc,          // srcdoc argument for iframe
++                       this,            // For reloads we are the source
++                       baseURI,
++                       nullptr,         // No nsIDocShell
++                       nullptr);        // No nsIRequest
+   }
+ 
+   return rv;
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::Stop(uint32_t aStopFlags)
+ {
+@@ -9463,27 +9480,28 @@ CopyFavicon(nsIURI* aOldURI, nsIURI* aNe
+ #endif
+ }
+ 
+ } // anonymous namespace
+ 
+ class InternalLoadEvent : public nsRunnable
+ {
+ public:
+-  InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI,
++  InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI, nsIURI* aOriginalURI,
+                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
+                     nsISupports* aOwner, uint32_t aFlags,
+                     const char* aTypeHint, nsIInputStream* aPostData,
+                     nsIInputStream* aHeadersData, uint32_t aLoadType,
+                     nsISHEntry* aSHEntry, bool aFirstParty,
+                     const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell,
+                     nsIURI* aBaseURI)
+     : mSrcdoc(aSrcdoc)
+     , mDocShell(aDocShell)
+     , mURI(aURI)
++    , mOriginalURI(aOriginalURI)
+     , mReferrer(aReferrer)
+     , mReferrerPolicy(aReferrerPolicy)
+     , mOwner(aOwner)
+     , mPostData(aPostData)
+     , mHeadersData(aHeadersData)
+     , mSHEntry(aSHEntry)
+     , mFlags(aFlags)
+     , mLoadType(aLoadType)
+@@ -9494,34 +9512,36 @@ public:
+     // Make sure to keep null things null as needed
+     if (aTypeHint) {
+       mTypeHint = aTypeHint;
+     }
+   }
+ 
+   NS_IMETHOD Run()
+   {
+-    return mDocShell->InternalLoad(mURI, mReferrer,
+-                                   mReferrerPolicy,
+-                                   mOwner, mFlags,
+-                                   nullptr, mTypeHint.get(),
+-                                   NullString(), mPostData, mHeadersData,
+-                                   mLoadType, mSHEntry, mFirstParty,
+-                                   mSrcdoc, mSourceDocShell, mBaseURI,
+-                                   nullptr, nullptr);
++    return mDocShell->InternalLoad2(mURI, mOriginalURI,
++                                    mReferrer,
++                                    mReferrerPolicy,
++                                    mOwner, mFlags,
++                                    nullptr, mTypeHint.get(),
++                                    NullString(), mPostData, mHeadersData,
++                                    mLoadType, mSHEntry, mFirstParty,
++                                    mSrcdoc, mSourceDocShell, mBaseURI,
++                                    nullptr, nullptr);
+   }
+ 
+ private:
+   // Use IDL strings so .get() returns null by default
+   nsXPIDLString mWindowTarget;
+   nsXPIDLCString mTypeHint;
+   nsString mSrcdoc;
+ 
+   nsRefPtr<nsDocShell> mDocShell;
+   nsCOMPtr<nsIURI> mURI;
++  nsCOMPtr<nsIURI> mOriginalURI;
+   nsCOMPtr<nsIURI> mReferrer;
+   uint32_t mReferrerPolicy;
+   nsCOMPtr<nsISupports> mOwner;
+   nsCOMPtr<nsIInputStream> mPostData;
+   nsCOMPtr<nsIInputStream> mHeadersData;
+   nsCOMPtr<nsISHEntry> mSHEntry;
+   uint32_t mFlags;
+   uint32_t mLoadType;
+@@ -9584,16 +9604,43 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+                          nsISHEntry* aSHEntry,
+                          bool aFirstParty,
+                          const nsAString& aSrcdoc,
+                          nsIDocShell* aSourceDocShell,
+                          nsIURI* aBaseURI,
+                          nsIDocShell** aDocShell,
+                          nsIRequest** aRequest)
+ {
++  return InternalLoad2(aURI, nullptr, aReferrer, aReferrerPolicy, aOwner,
++                       aFlags, aWindowTarget, aTypeHint, aFileName, aPostData,
++                       aHeadersData, aLoadType, aSHEntry, aFirstParty, aSrcdoc,
++                       aSourceDocShell, aBaseURI, aDocShell, aRequest);
++}
++
++NS_IMETHODIMP
++nsDocShell::InternalLoad2(nsIURI* aURI,
++                          nsIURI* aOriginalURI,
++                          nsIURI* aReferrer,
++                          uint32_t aReferrerPolicy,
++                          nsISupports* aOwner,
++                          uint32_t aFlags,
++                          const char16_t* aWindowTarget,
++                          const char* aTypeHint,
++                          const nsAString& aFileName,
++                          nsIInputStream* aPostData,
++                          nsIInputStream* aHeadersData,
++                          uint32_t aLoadType,
++                          nsISHEntry* aSHEntry,
++                          bool aFirstParty,
++                          const nsAString& aSrcdoc,
++                          nsIDocShell* aSourceDocShell,
++                          nsIURI* aBaseURI,
++                          nsIDocShell** aDocShell,
++                          nsIRequest** aRequest)
++{
+   nsresult rv = NS_OK;
+   mOriginalUriString.Truncate();
+ 
+ #ifdef PR_LOGGING
+   if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) {
+     nsAutoCString spec;
+     if (aURI) {
+       aURI->GetSpec(spec);
+@@ -9831,34 +9878,58 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+       targetDocShell = do_QueryInterface(webNav);
+     }
+ 
+     //
+     // Transfer the load to the target DocShell...  Pass nullptr as the
+     // window target name from to prevent recursive retargeting!
+     //
+     if (NS_SUCCEEDED(rv) && targetDocShell) {
+-      rv = targetDocShell->InternalLoad(aURI,
+-                                        aReferrer,
+-                                        aReferrerPolicy,
+-                                        owner,
+-                                        aFlags,
+-                                        nullptr,         // No window target
+-                                        aTypeHint,
+-                                        NullString(),    // No forced download
+-                                        aPostData,
+-                                        aHeadersData,
+-                                        aLoadType,
+-                                        aSHEntry,
+-                                        aFirstParty,
+-                                        aSrcdoc,
+-                                        aSourceDocShell,
+-                                        aBaseURI,
+-                                        aDocShell,
+-                                        aRequest);
++      nsCOMPtr<nsIDocShell_ESR38_2> dsESR38 = do_QueryInterface(targetDocShell);
++      if (dsESR38) {
++        rv = dsESR38->InternalLoad2(aURI,
++                                    aOriginalURI,
++                                    aReferrer,
++                                    aReferrerPolicy,
++                                    owner,
++                                    aFlags,
++                                    nullptr,         // No window target
++                                    aTypeHint,
++                                    NullString(),    // No forced download
++                                    aPostData,
++                                    aHeadersData,
++                                    aLoadType,
++                                    aSHEntry,
++                                    aFirstParty,
++                                    aSrcdoc,
++                                    aSourceDocShell,
++                                    aBaseURI,
++                                    aDocShell,
++                                    aRequest);
++      } else {
++        rv = targetDocShell->InternalLoad(aURI,
++                                          aReferrer,
++                                          aReferrerPolicy,
++                                          owner,
++                                          aFlags,
++                                          nullptr,         // No window target
++                                          aTypeHint,
++                                          NullString(),    // No forced download
++                                          aPostData,
++                                          aHeadersData,
++                                          aLoadType,
++                                          aSHEntry,
++                                          aFirstParty,
++                                          aSrcdoc,
++                                          aSourceDocShell,
++                                          aBaseURI,
++                                          aDocShell,
++                                          aRequest);
++      }
++
+       if (rv == NS_ERROR_NO_CONTENT) {
+         // XXXbz except we never reach this code!
+         if (isNewWindow) {
+           //
+           // At this point, a new window has been created, but the
+           // URI did not have any data associated with it...
+           //
+           // So, the best we can do, is to tear down the new window
+@@ -9913,17 +9984,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+       // the unload event also a replace load, so we don't
+       // create extra history entries.
+       if (LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
+         mLoadType = LOAD_NORMAL_REPLACE;
+       }
+ 
+       // Do this asynchronously
+       nsCOMPtr<nsIRunnable> ev =
+-        new InternalLoadEvent(this, aURI, aReferrer,
++        new InternalLoadEvent(this, aURI, aOriginalURI, aReferrer,
+                               aReferrerPolicy, aOwner, aFlags,
+                               aTypeHint, aPostData, aHeadersData,
+                               aLoadType, aSHEntry, aFirstParty, aSrcdoc,
+                               aSourceDocShell, aBaseURI);
+       return NS_DispatchToCurrentThread(ev);
+     }
+ 
+     // Just ignore this load attempt
+@@ -10371,17 +10442,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+   }
+ 
+   net::PredictorLearn(aURI, nullptr,
+                       nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, this);
+   net::PredictorPredict(aURI, nullptr,
+                         nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
+ 
+   nsCOMPtr<nsIRequest> req;
+-  rv = DoURILoad(aURI, aReferrer,
++  rv = DoURILoad(aURI, aOriginalURI, aReferrer,
+                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
+                  aReferrerPolicy,
+                  owner, aTypeHint, aFileName, aPostData, aHeadersData,
+                  aFirstParty, aDocShell, getter_AddRefs(req),
+                  (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
+                  (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
+                  (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
+                  srcdoc, aBaseURI, contentType);
+@@ -10445,16 +10516,17 @@ nsDocShell::GetInheritedPrincipal(bool a
+     return docPrincipal;
+   }
+ 
+   return nullptr;
+ }
+ 
+ nsresult
+ nsDocShell::DoURILoad(nsIURI* aURI,
++                      nsIURI* aOriginalURI,
+                       nsIURI* aReferrerURI,
+                       bool aSendReferrer,
+                       uint32_t aReferrerPolicy,
+                       nsISupports* aOwner,
+                       const char* aTypeHint,
+                       const nsAString& aFileName,
+                       nsIInputStream* aPostData,
+                       nsIInputStream* aHeadersData,
+@@ -10652,17 +10724,22 @@ nsDocShell::DoURILoad(nsIURI* aURI,
+   }
+ 
+   // Make sure to give the caller a channel if we managed to create one
+   // This is important for correct error page/session history interaction
+   if (aRequest) {
+     NS_ADDREF(*aRequest = channel);
+   }
+ 
+-  channel->SetOriginalURI(aURI);
++  if (aOriginalURI) {
++    channel->SetOriginalURI(aOriginalURI);
++  } else {
++    channel->SetOriginalURI(aURI);
++  }
++
+   if (aTypeHint && *aTypeHint) {
+     channel->SetContentType(nsDependentCString(aTypeHint));
+     mContentTypeHint = aTypeHint;
+   } else {
+     mContentTypeHint.Truncate();
+   }
+ 
+   if (!aFileName.IsVoid()) {
+@@ -11624,16 +11701,20 @@ nsDocShell::AddState(JS::Handle<JS::Valu
+ 
+     // AddToSessionHistory may not modify mOSHE.  In case it doesn't,
+     // we'll just set mOSHE here.
+     mOSHE = newSHEntry;
+ 
+   } else {
+     newSHEntry = mOSHE;
+     newSHEntry->SetURI(newURI);
++    nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(newSHEntry);
++    if (entryESR38) {
++      entryESR38->SetOriginalURI(newURI);
++    }
+   }
+ 
+   // Step 4: Modify new/original session history entry and clear its POST
+   // data, if there is any.
+   newSHEntry->SetStateData(scContainer);
+   newSHEntry->SetPostData(nullptr);
+ 
+   // If this push/replaceState changed the document's current URI and the new
+@@ -11816,16 +11897,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
+ 
+     if (!entry) {
+       return NS_ERROR_OUT_OF_MEMORY;
+     }
+   }
+ 
+   // Get the post data & referrer
+   nsCOMPtr<nsIInputStream> inputStream;
++  nsCOMPtr<nsIURI> originalURI;
+   nsCOMPtr<nsIURI> referrerURI;
+   uint32_t referrerPolicy = mozilla::net::RP_Default;
+   nsCOMPtr<nsISupports> cacheKey;
+   nsCOMPtr<nsISupports> owner = aOwner;
+   bool expired = false;
+   bool discardLayoutState = false;
+   nsCOMPtr<nsICachingChannel> cacheChannel;
+   if (aChannel) {
+@@ -11843,16 +11925,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
+     if (!httpChannel) {
+       GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
+     }
+     if (httpChannel) {
+       nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
+       if (uploadChannel) {
+         uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
+       }
++      httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
+       httpChannel->GetReferrer(getter_AddRefs(referrerURI));
+       httpChannel->GetReferrerPolicy(&referrerPolicy);
+ 
+       discardLayoutState = ShouldDiscardLayoutState(httpChannel);
+     }
+     aChannel->GetOwner(getter_AddRefs(owner));
+     if (!owner) {
+       nsCOMPtr<nsILoadInfo> loadInfo;
+@@ -11875,16 +11958,21 @@ nsDocShell::AddToSessionHistory(nsIURI* 
+                 EmptyString(),     // Title
+                 inputStream,       // Post data stream
+                 nullptr,           // LayoutHistory state
+                 cacheKey,          // CacheKey
+                 mContentTypeHint,  // Content-type
+                 owner,             // Channel or provided owner
+                 mHistoryID,
+                 mDynamicallyCreated);
++
++  nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(entry);
++  if (entryESR38) {
++    entryESR38->SetOriginalURI(originalURI);
++  }
+   entry->SetReferrerURI(referrerURI);
+   entry->SetReferrerPolicy(referrerPolicy);
+   nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
+   if (inStrmChan) {
+     bool isSrcdocChannel;
+     inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
+     if (isSrcdocChannel) {
+       nsAutoString srcdoc;
+@@ -11976,25 +12064,32 @@ nsDocShell::AddToSessionHistory(nsIURI* 
+ nsresult
+ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
+ {
+   if (!IsNavigationAllowed()) {
+     return NS_OK;
+   }
+ 
+   nsCOMPtr<nsIURI> uri;
++  nsCOMPtr<nsIURI> originalURI;
+   nsCOMPtr<nsIInputStream> postData;
+   nsCOMPtr<nsIURI> referrerURI;
+   uint32_t referrerPolicy;
+   nsAutoCString contentType;
+   nsCOMPtr<nsISupports> owner;
+ 
+   NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
+ 
+   NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
++
++  nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(aEntry);
++  if (entryESR38) {
++    NS_ENSURE_SUCCESS(entryESR38->GetOriginalURI(getter_AddRefs(originalURI)),
++                      NS_ERROR_FAILURE);
++  }
+   NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
+                     NS_ERROR_FAILURE);
+   NS_ENSURE_SUCCESS(aEntry->GetReferrerPolicy(&referrerPolicy),
+                     NS_ERROR_FAILURE);
+   NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)),
+                     NS_ERROR_FAILURE);
+   NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE);
+   NS_ENSURE_SUCCESS(aEntry->GetOwner(getter_AddRefs(owner)), NS_ERROR_FAILURE);
+@@ -12064,34 +12159,35 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
+   } else {
+     srcdoc = NullString();
+   }
+ 
+   // Passing nullptr as aSourceDocShell gives the same behaviour as before
+   // aSourceDocShell was introduced. According to spec we should be passing
+   // the source browsing context that was used when the history entry was
+   // first created. bug 947716 has been created to address this issue.
+-  rv = InternalLoad(uri,
+-                    referrerURI,
+-                    referrerPolicy,
+-                    owner,
+-                    flags,
+-                    nullptr,            // No window target
+-                    contentType.get(),  // Type hint
+-                    NullString(),       // No forced file download
+-                    postData,           // Post data stream
+-                    nullptr,            // No headers stream
+-                    aLoadType,          // Load type
+-                    aEntry,             // SHEntry
+-                    true,
+-                    srcdoc,
+-                    nullptr,            // Source docshell, see comment above
+-                    baseURI,
+-                    nullptr,            // No nsIDocShell
+-                    nullptr);           // No nsIRequest
++  rv = InternalLoad2(uri,
++                     originalURI,
++                     referrerURI,
++                     referrerPolicy,
++                     owner,
++                     flags,
++                     nullptr,            // No window target
++                     contentType.get(),  // Type hint
++                     NullString(),       // No forced file download
++                     postData,           // Post data stream
++                     nullptr,            // No headers stream
++                     aLoadType,          // Load type
++                     aEntry,             // SHEntry
++                     true,
++                     srcdoc,
++                     nullptr,            // Source docshell, see comment above
++                     baseURI,
++                     nullptr,            // No nsIDocShell
++                     nullptr);           // No nsIRequest
+   return rv;
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::GetShouldSaveLayoutState(bool* aShould)
+ {
+   *aShould = false;
+   if (mOSHE) {
+@@ -13527,35 +13623,36 @@ nsDocShell::OnLinkClickSync(nsIContent* 
+   // with it under InternalLoad; we do _not_ want to change the URI
+   // our caller passed in.
+   nsCOMPtr<nsIURI> clonedURI;
+   aURI->Clone(getter_AddRefs(clonedURI));
+   if (!clonedURI) {
+     return NS_ERROR_OUT_OF_MEMORY;
+   }
+ 
+-  nsresult rv = InternalLoad(clonedURI,                 // New URI
+-                             referer,                   // Referer URI
+-                             refererPolicy,             // Referer policy
+-                             aContent->NodePrincipal(), // Owner is our node's
+-                                                        // principal
+-                             flags,
+-                             target.get(),              // Window target
+-                             NS_LossyConvertUTF16toASCII(typeHint).get(),
+-                             aFileName,                 // Download as file
+-                             aPostDataStream,           // Post data stream
+-                             aHeadersDataStream,        // Headers stream
+-                             LOAD_LINK,                 // Load type
+-                             nullptr,                   // No SHEntry
+-                             true,                      // first party site
+-                             NullString(),              // No srcdoc
+-                             this,                      // We are the source
+-                             nullptr,                   // baseURI not needed
+-                             aDocShell,                 // DocShell out-param
+-                             aRequest);                 // Request out-param
++  nsresult rv = InternalLoad2(clonedURI,                 // New URI
++                              nullptr,                   // Original URI
++                              referer,                   // Referer URI
++                              refererPolicy,             // Referer policy
++                              aContent->NodePrincipal(), // Owner is our node's
++                                                         // principal
++                              flags,
++                              target.get(),              // Window target
++                              NS_LossyConvertUTF16toASCII(typeHint).get(),
++                              aFileName,                 // Download as file
++                              aPostDataStream,           // Post data stream
++                              aHeadersDataStream,        // Headers stream
++                              LOAD_LINK,                 // Load type
++                              nullptr,                   // No SHEntry
++                              true,                      // first party site
++                              NullString(),              // No srcdoc
++                              this,                      // We are the source
++                              nullptr,                   // baseURI not needed
++                              aDocShell,                 // DocShell out-param
++                              aRequest);                 // Request out-param
+   if (NS_SUCCEEDED(rv)) {
+     DispatchPings(aContent, aURI, referer, refererPolicy);
+   }
+   return rv;
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::OnOverLink(nsIContent* aContent,
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -132,17 +132,17 @@ enum eCharsetReloadState
+ };
+ 
+ //*****************************************************************************
+ //***    nsDocShell
+ //*****************************************************************************
+ 
+ class nsDocShell final
+   : public nsDocLoader
+-  , public nsIDocShell_ESR38
++  , public nsIDocShell_ESR38_2
+   , public nsIWebNavigation
+   , public nsIBaseWindow
+   , public nsIScrollable
+   , public nsITextScroll
+   , public nsIDocCharset
+   , public nsIContentViewerContainer
+   , public nsIRefreshURI
+   , public nsIWebProgressListener
+@@ -164,16 +164,17 @@ public:
+   nsDocShell();
+ 
+   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
+ 
+   virtual nsresult Init() override;
+ 
+   NS_DECL_ISUPPORTS_INHERITED
+ 
++  NS_DECL_NSIDOCSHELL_ESR38_2
+   NS_DECL_NSIDOCSHELL_ESR38
+   NS_DECL_NSIDOCSHELL
+   NS_DECL_NSIDOCSHELLTREEITEM
+   NS_DECL_NSIWEBNAVIGATION
+   NS_DECL_NSIBASEWINDOW
+   NS_DECL_NSISCROLLABLE
+   NS_DECL_NSITEXTSCROLL
+   NS_DECL_NSIDOCCHARSET
+@@ -312,17 +313,20 @@ protected:
+   // at the parent.
+   nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument);
+ 
+   // Actually open a channel and perform a URI load.  Note: whatever owner is
+   // passed to this function will be set on the channel.  Callers who wish to
+   // not have an owner on the channel should just pass null.
+   // If aSrcdoc is not void, the load will be considered as a srcdoc load,
+   // and the contents of aSrcdoc will be loaded instead of aURI.
++  // aOriginalURI will be set as the originalURI on the channel that does the
++  // load. If aOriginalURI is null, aURI will be set as the originalURI.
+   nsresult DoURILoad(nsIURI* aURI,
++                     nsIURI* aOriginalURI,
+                      nsIURI* aReferrer,
+                      bool aSendReferrer,
+                      uint32_t aReferrerPolicy,
+                      nsISupports* aOwner,
+                      const char* aTypeHint,
+                      const nsAString& aFileName,
+                      nsIInputStream* aPostData,
+                      nsIInputStream* aHeadersData,
+diff --git a/docshell/base/nsDocShellLoadInfo.cpp b/docshell/base/nsDocShellLoadInfo.cpp
+--- a/docshell/base/nsDocShellLoadInfo.cpp
++++ b/docshell/base/nsDocShellLoadInfo.cpp
+@@ -34,16 +34,17 @@ nsDocShellLoadInfo::~nsDocShellLoadInfo(
+ // nsDocShellLoadInfo::nsISupports
+ //*****************************************************************************
+ 
+ NS_IMPL_ADDREF(nsDocShellLoadInfo)
+ NS_IMPL_RELEASE(nsDocShellLoadInfo)
+ 
+ NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo)
+   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo)
++  NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo_ESR38)
+   NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo)
+ NS_INTERFACE_MAP_END
+ 
+ //*****************************************************************************
+ // nsDocShellLoadInfo::nsIDocShellLoadInfo
+ //*****************************************************************************
+ 
+ NS_IMETHODIMP
+@@ -59,16 +60,33 @@ nsDocShellLoadInfo::GetReferrer(nsIURI**
+ NS_IMETHODIMP
+ nsDocShellLoadInfo::SetReferrer(nsIURI* aReferrer)
+ {
+   mReferrer = aReferrer;
+   return NS_OK;
+ }
+ 
+ NS_IMETHODIMP
++nsDocShellLoadInfo::GetOriginalURI(nsIURI** aOriginalURI)
++{
++  NS_ENSURE_ARG_POINTER(aOriginalURI);
++
++  *aOriginalURI = mOriginalURI;
++  NS_IF_ADDREF(*aOriginalURI);
++  return NS_OK;
++}
++
++NS_IMETHODIMP
++nsDocShellLoadInfo::SetOriginalURI(nsIURI* aOriginalURI)
++{
++  mOriginalURI = aOriginalURI;
++  return NS_OK;
++}
++
++NS_IMETHODIMP
+ nsDocShellLoadInfo::GetOwner(nsISupports** aOwner)
+ {
+   NS_ENSURE_ARG_POINTER(aOwner);
+ 
+   *aOwner = mOwner;
+   NS_IF_ADDREF(*aOwner);
+   return NS_OK;
+ }
+diff --git a/docshell/base/nsDocShellLoadInfo.h b/docshell/base/nsDocShellLoadInfo.h
+--- a/docshell/base/nsDocShellLoadInfo.h
++++ b/docshell/base/nsDocShellLoadInfo.h
+@@ -14,29 +14,31 @@
+ // Interfaces Needed
+ #include "nsIDocShellLoadInfo.h"
+ 
+ class nsIInputStream;
+ class nsISHEntry;
+ class nsIURI;
+ class nsIDocShell;
+ 
+-class nsDocShellLoadInfo : public nsIDocShellLoadInfo
++class nsDocShellLoadInfo : public nsIDocShellLoadInfo_ESR38
+ {
+ public:
+   nsDocShellLoadInfo();
+ 
+   NS_DECL_ISUPPORTS
++  NS_DECL_NSIDOCSHELLLOADINFO_ESR38
+   NS_DECL_NSIDOCSHELLLOADINFO
+ 
+ protected:
+   virtual ~nsDocShellLoadInfo();
+ 
+ protected:
+   nsCOMPtr<nsIURI> mReferrer;
++  nsCOMPtr<nsIURI> mOriginalURI;
+   nsCOMPtr<nsISupports> mOwner;
+   bool mInheritOwner;
+   bool mOwnerIsExplicit;
+   bool mSendReferrer;
+   nsDocShellInfoReferrerPolicy mReferrerPolicy;
+   nsDocShellInfoLoadType mLoadType;
+   nsCOMPtr<nsISHEntry> mSHEntry;
+   nsString mTarget;
+diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
+--- a/docshell/base/nsIDocShell.idl
++++ b/docshell/base/nsIDocShell.idl
+@@ -1059,8 +1059,66 @@ interface nsIDocShell : nsIDocShellTreeI
+ interface nsIDocShell_ESR38 : nsIDocShell
+ {
+   /**
+    * True if new child docshells should allow content retargeting.
+    * Setting allowContentRetargeting also overwrites this value.
+    */
+   [infallible] attribute boolean allowContentRetargetingOnChildren;
+ };
++
++[scriptable, builtinclass, uuid(607604b6-8fe0-4d2c-8a6c-44f5f31a6e02)]
++interface nsIDocShell_ESR38_2 : nsIDocShell_ESR38
++{
++  /**
++   * Loads the given URI.  This method is identical to loadURI(...) except
++   * that its parameter list is broken out instead of being packaged inside
++   * of an nsIDocShellLoadInfo object...
++   *
++   * @param aURI            - The URI to load.
++   * @param aOriginalURI    - The URI to set as the originalURI on the channel
++   *                          that does the load. If null, aURI will be set as
++   *                          the originalURI.
++   * @param aReferrer       - Referring URI
++   * @param aReferrerPolicy - Referrer policy
++   * @param aOwner          - Owner (security principal) 
++   * @param aInheritOwner   - Flag indicating whether the owner of the current
++   *                          document should be inherited if aOwner is null.
++   * @param aStopActiveDoc  - Flag indicating whether loading the current
++   *                          document should be stopped.
++   * @param aWindowTarget   - Window target for the load.
++   * @param aTypeHint       - A hint as to the content-type of the resulting
++   *                          data.  May be null or empty if no hint.
++   * @param aFileName       - Non-null when the link should be downloaded as
++                              the given filename.
++   * @param aPostDataStream - Post data stream (if POSTing)
++   * @param aHeadersStream  - Stream containing "extra" request headers...
++   * @param aLoadFlags      - Flags to modify load behaviour. Flags are defined
++   *                          in nsIWebNavigation.
++   * @param aSHEntry        - Active Session History entry (if loading from SH)
++   * @param aSrcdoc           When INTERNAL_LOAD_FLAGS_IS_SRCDOC is set, the
++   *                          contents of this parameter will be loaded instead
++   *                          of aURI.
++   * @param aSourceDocShell - The source browsing context for the navigation.
++   * @param aBaseURI        - The base URI to be used for the load.  Set in
++   *                          srcdoc loads as it cannot otherwise be inferred
++   *                          in certain situations such as view-source.
++   */
++  [noscript]void internalLoad2(in nsIURI aURI,
++                               in nsIURI aOriginalURI,
++                               in nsIURI aReferrer,
++                               in unsigned long aReferrerPolicy,
++                               in nsISupports aOwner,
++                               in uint32_t aFlags,
++                               in wstring aWindowTarget,
++                               in string aTypeHint,
++                               in AString aFileName,
++                               in nsIInputStream aPostDataStream,
++                               in nsIInputStream aHeadersStream,
++                               in unsigned long aLoadFlags,
++                               in nsISHEntry aSHEntry,
++                               in boolean firstParty,
++                               in AString aSrcdoc,
++                               in nsIDocShell aSourceDocShell,
++                               in nsIURI aBaseURI,
++                               out nsIDocShell aDocShell,
++                               out nsIRequest aRequest);
++};
+diff --git a/docshell/base/nsIDocShellLoadInfo.idl b/docshell/base/nsIDocShellLoadInfo.idl
+--- a/docshell/base/nsIDocShellLoadInfo.idl
++++ b/docshell/base/nsIDocShellLoadInfo.idl
+@@ -106,8 +106,17 @@ interface nsIDocShellLoadInfo : nsISuppo
+     attribute nsIDocShell sourceDocShell;
+ 
+     /**
+      * Used for srcdoc loads to give view-source knowledge of the load's base
+      * URI as this information isn't embedded in the load's URI.
+      */
+     attribute nsIURI baseURI;
+ };
++
++[scriptable, uuid(9d3bc466-5efe-414d-ae8b-3830b45877bb)]
++interface nsIDocShellLoadInfo_ESR38 : nsIDocShellLoadInfo
++{
++    /**
++     * The originalURI to be passed to nsIDocShell.internalLoad. May be null.
++     */
++    attribute nsIURI originalURI;
++};
+diff --git a/docshell/shistory/public/nsISHEntry.idl b/docshell/shistory/public/nsISHEntry.idl
+--- a/docshell/shistory/public/nsISHEntry.idl
++++ b/docshell/shistory/public/nsISHEntry.idl
+@@ -319,8 +319,18 @@ interface nsISHEntryInternal : nsISuppor
+ #define NS_SHENTRY_CID \
+ {0xbfd1a791, 0xad9f, 0x11d3, {0xbd, 0xc7, 0x0, 0x50, 0x4, 0xa, 0x9b, 0x44}}
+ 
+ #define NS_SHENTRY_CONTRACTID \
+     "@mozilla.org/browser/session-history-entry;1"
+ 
+ %}
+ 
++[scriptable, uuid(e45ab6ef-3485-449c-b91c-0846b2bf6faf)]
++interface nsISHEntry_ESR38 : nsISHEntry
++{
++    /**
++     * A readonly property that returns the original URI of the current entry.
++     * If an entry is the result of a redirect this attribute holds original
++     * URI. The object returned is of type nsIURI
++     */
++    attribute nsIURI originalURI;
++};
+diff --git a/docshell/shistory/src/nsSHEntry.cpp b/docshell/shistory/src/nsSHEntry.cpp
+--- a/docshell/shistory/src/nsSHEntry.cpp
++++ b/docshell/shistory/src/nsSHEntry.cpp
+@@ -38,16 +38,17 @@ nsSHEntry::nsSHEntry()
+   , mIsSrcdocEntry(false)
+ {
+   mShared = new nsSHEntryShared();
+ }
+ 
+ nsSHEntry::nsSHEntry(const nsSHEntry &other)
+   : mShared(other.mShared)
+   , mURI(other.mURI)
++  , mOriginalURI(other.mOriginalURI)
+   , mReferrerURI(other.mReferrerURI)
+   , mReferrerPolicy(other.mReferrerPolicy)
+   , mTitle(other.mTitle)
+   , mPostData(other.mPostData)
+   , mLoadType(0)         // XXX why not copy?
+   , mID(other.mID)
+   , mScrollPositionX(0)  // XXX why not copy?
+   , mScrollPositionY(0)  // XXX why not copy?
+@@ -74,17 +75,17 @@ nsSHEntry::~nsSHEntry()
+   // Null out the mParent pointers on all our kids.
+   mChildren.EnumerateForwards(ClearParentPtr, nullptr);
+ }
+ 
+ //*****************************************************************************
+ //    nsSHEntry: nsISupports
+ //*****************************************************************************
+ 
+-NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
++NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry_ESR38, nsISHEntry, nsISHEntryInternal)
+ 
+ //*****************************************************************************
+ //    nsSHEntry: nsISHEntry
+ //*****************************************************************************
+ 
+ NS_IMETHODIMP nsSHEntry::SetScrollPosition(int32_t x, int32_t y)
+ {
+   mScrollPositionX = x;
+@@ -119,16 +120,29 @@ NS_IMETHODIMP nsSHEntry::GetURI(nsIURI**
+ }
+ 
+ NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI)
+ {
+   mURI = aURI;
+   return NS_OK;
+ }
+ 
++NS_IMETHODIMP nsSHEntry::GetOriginalURI(nsIURI** aOriginalURI)
++{
++  *aOriginalURI = mOriginalURI;
++  NS_IF_ADDREF(*aOriginalURI);
++  return NS_OK;
++}
++
++NS_IMETHODIMP nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI)
++{
++  mOriginalURI = aOriginalURI;
++  return NS_OK;
++}
++
+ NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI)
+ {
+   *aReferrerURI = mReferrerURI;
+   NS_IF_ADDREF(*aReferrerURI);
+   return NS_OK;
+ }
+ 
+ NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
+diff --git a/docshell/shistory/src/nsSHEntry.h b/docshell/shistory/src/nsSHEntry.h
+--- a/docshell/shistory/src/nsSHEntry.h
++++ b/docshell/shistory/src/nsSHEntry.h
+@@ -17,25 +17,26 @@
+ // Interfaces needed
+ #include "nsISHEntry.h"
+ #include "nsISHContainer.h"
+ 
+ class nsSHEntryShared;
+ class nsIInputStream;
+ class nsIURI;
+ 
+-class nsSHEntry final : public nsISHEntry,
++class nsSHEntry final : public nsISHEntry_ESR38,
+                             public nsISHContainer,
+                             public nsISHEntryInternal
+ {
+ public: 
+   nsSHEntry();
+   nsSHEntry(const nsSHEntry &other);
+ 
+   NS_DECL_ISUPPORTS
++  NS_DECL_NSISHENTRY_ESR38
+   NS_DECL_NSISHENTRY
+   NS_DECL_NSISHENTRYINTERNAL
+   NS_DECL_NSISHCONTAINER
+ 
+   void DropPresentationState();
+ 
+   static nsresult Startup();
+   static void Shutdown();
+@@ -44,16 +45,17 @@ private:
+   ~nsSHEntry();
+ 
+   // We share the state in here with other SHEntries which correspond to the
+   // same document.
+   nsRefPtr<nsSHEntryShared> mShared;
+ 
+   // See nsSHEntry.idl for comments on these members.
+   nsCOMPtr<nsIURI>         mURI;
++  nsCOMPtr<nsIURI>         mOriginalURI;
+   nsCOMPtr<nsIURI>         mReferrerURI;
+   uint32_t                 mReferrerPolicy;
+   nsString                 mTitle;
+   nsCOMPtr<nsIInputStream> mPostData;
+   uint32_t                 mLoadType;
+   uint32_t                 mID;
+   int32_t                  mScrollPositionX;
+   int32_t                  mScrollPositionY;
+diff --git a/docshell/shistory/src/nsSHistory.cpp b/docshell/shistory/src/nsSHistory.cpp
+--- a/docshell/shistory/src/nsSHistory.cpp
++++ b/docshell/shistory/src/nsSHistory.cpp
+@@ -1779,16 +1779,26 @@ nsSHistory::InitiateLoad(nsISHEntry * aF
+    * so that proper loadType is maintained through out a frameset
+    */
+   aFrameEntry->SetLoadType(aLoadType);    
+   aFrameDS->CreateLoadInfo (getter_AddRefs(loadInfo));
+ 
+   loadInfo->SetLoadType(aLoadType);
+   loadInfo->SetSHEntry(aFrameEntry);
+ 
++  nsCOMPtr<nsIURI> originalURI;
++  nsCOMPtr<nsISHEntry_ESR38> feESR38 = do_QueryInterface(aFrameEntry);
++  if (feESR38) {
++    feESR38->GetOriginalURI(getter_AddRefs(originalURI));
++  }
++  nsCOMPtr<nsIDocShellLoadInfo_ESR38> liESR38 = do_QueryInterface(loadInfo);
++  if (liESR38) {
++    liESR38->SetOriginalURI(originalURI);
++  }
++
+   nsCOMPtr<nsIURI> nextURI;
+   aFrameEntry->GetURI(getter_AddRefs(nextURI));
+   // Time   to initiate a document load
+   return aFrameDS->LoadURI(nextURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, false);
+ 
+ }
+ 
+ 
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch
new file mode 100644
index 0000000000..2b711b1761
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch
@@ -0,0 +1,356 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/c1d67bd4c993
+
+# HG changeset patch
+# User Timothy Nikkel <tnikkel@gmail.com>
+# Date 1454023801 21600
+# Node ID c1d67bd4c993b9e344c68954e6f0392c82b81e38
+# Parent  530559abe159d3c23f078d673d30ff03d9c244e2
+Bug 1224979 - Check if we compute usable filters for the downscaler, and if not put the downscaler in error state so it's not used. r=edwin, a=al
+
+diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp
+new file mode 100644
+--- /dev/null
++++ b/image/Downscaler.cpp
+@@ -0,0 +1,340 @@
++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ *
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#include "Downscaler.h"
++
++#include <algorithm>
++#include <ctime>
++#include "gfxPrefs.h"
++#include "image_operations.h"
++#include "mozilla/SSE.h"
++#include "convolver.h"
++#include "skia/include/core/SkTypes.h"
++
++using std::max;
++using std::swap;
++
++namespace mozilla {
++namespace image {
++
++Downscaler::Downscaler(const nsIntSize& aTargetSize)
++  : mTargetSize(aTargetSize)
++  , mOutputBuffer(nullptr)
++  , mXFilter(MakeUnique<skia::ConvolutionFilter1D>())
++  , mYFilter(MakeUnique<skia::ConvolutionFilter1D>())
++  , mWindowCapacity(0)
++  , mHasAlpha(true)
++  , mFlipVertically(false)
++{
++  MOZ_ASSERT(gfxPrefs::ImageDownscaleDuringDecodeEnabled(),
++             "Downscaling even though downscale-during-decode is disabled?");
++  MOZ_ASSERT(mTargetSize.width > 0 && mTargetSize.height > 0,
++             "Invalid target size");
++}
++
++Downscaler::~Downscaler()
++{
++  ReleaseWindow();
++}
++
++void
++Downscaler::ReleaseWindow()
++{
++  if (!mWindow) {
++    return;
++  }
++
++  for (int32_t i = 0; i < mWindowCapacity; ++i) {
++    delete[] mWindow[i];
++  }
++
++  mWindow = nullptr;
++  mWindowCapacity = 0;
++}
++
++nsresult
++Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
++                       const Maybe<nsIntRect>& aFrameRect,
++                       uint8_t* aOutputBuffer,
++                       bool aHasAlpha,
++                       bool aFlipVertically /* = false */)
++{
++  MOZ_ASSERT(aOutputBuffer);
++  MOZ_ASSERT(mTargetSize != aOriginalSize,
++             "Created a downscaler, but not downscaling?");
++  MOZ_ASSERT(mTargetSize.width <= aOriginalSize.width,
++             "Created a downscaler, but width is larger");
++  MOZ_ASSERT(mTargetSize.height <= aOriginalSize.height,
++             "Created a downscaler, but height is larger");
++  MOZ_ASSERT(aOriginalSize.width > 0 && aOriginalSize.height > 0,
++             "Invalid original size");
++
++  mFrameRect = aFrameRect.valueOr(nsIntRect(nsIntPoint(), aOriginalSize));
++  MOZ_ASSERT(mFrameRect.x >= 0 && mFrameRect.y >= 0 &&
++             mFrameRect.width >= 0 && mFrameRect.height >= 0,
++             "Frame rect must have non-negative components");
++  MOZ_ASSERT(nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
++               .Contains(mFrameRect),
++             "Frame rect must fit inside image");
++  MOZ_ASSERT_IF(!nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
++                  .IsEqualEdges(mFrameRect),
++                aHasAlpha);
++
++  mOriginalSize = aOriginalSize;
++  mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
++                   double(mOriginalSize.height) / mTargetSize.height);
++  mOutputBuffer = aOutputBuffer;
++  mHasAlpha = aHasAlpha;
++  mFlipVertically = aFlipVertically;
++
++  ReleaseWindow();
++
++  auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
++
++  skia::resize::ComputeFilters(resizeMethod,
++                               mOriginalSize.width, mTargetSize.width,
++                               0, mTargetSize.width,
++                               mXFilter.get());
++
++  if (mXFilter->max_filter() <= 0 || mXFilter->num_values() != mTargetSize.width) {
++    NS_WARNING("Failed to compute filters for image downscaling");
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
++
++  skia::resize::ComputeFilters(resizeMethod,
++                               mOriginalSize.height, mTargetSize.height,
++                               0, mTargetSize.height,
++                               mYFilter.get());
++
++  if (mYFilter->max_filter() <= 0 || mYFilter->num_values() != mTargetSize.height) {
++    NS_WARNING("Failed to compute filters for image downscaling");
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
++
++  // Allocate the buffer, which contains scanlines of the original image.
++  // pad by 15 to handle overreads by the simd code
++  size_t bufferLen = mOriginalSize.width * sizeof(uint32_t) + 15;
++  mRowBuffer.reset(new (fallible) uint8_t[bufferLen]);
++  if (MOZ_UNLIKELY(!mRowBuffer)) {
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
++
++  // Zero buffer to keep valgrind happy.
++  memset(mRowBuffer.get(), 0, bufferLen);
++
++  // Allocate the window, which contains horizontally downscaled scanlines. (We
++  // can store scanlines which are already downscale because our downscaling
++  // filter is separable.)
++  mWindowCapacity = mYFilter->max_filter();
++  mWindow.reset(new (fallible) uint8_t*[mWindowCapacity]);
++  if (MOZ_UNLIKELY(!mWindow)) {
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
++
++  bool anyAllocationFailed = false;
++  // pad by 15 to handle overreads by the simd code
++  const int rowSize = mTargetSize.width * sizeof(uint32_t) + 15;
++  for (int32_t i = 0; i < mWindowCapacity; ++i) {
++    mWindow[i] = new (fallible) uint8_t[rowSize];
++    anyAllocationFailed = anyAllocationFailed || mWindow[i] == nullptr;
++  }
++
++  if (MOZ_UNLIKELY(anyAllocationFailed)) {
++    // We intentionally iterate through the entire array even if an allocation
++    // fails, to ensure that all the pointers in it are either valid or nullptr.
++    // That in turn ensures that ReleaseWindow() can clean up correctly.
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
++
++  ResetForNextProgressivePass();
++
++  return NS_OK;
++}
++
++void
++Downscaler::SkipToRow(int32_t aRow)
++{
++  if (mCurrentInLine < aRow) {
++    ClearRow();
++    do {
++      CommitRow();
++    } while (mCurrentInLine < aRow);
++  }
++}
++
++void
++Downscaler::ResetForNextProgressivePass()
++{
++  mPrevInvalidatedLine = 0;
++  mCurrentOutLine = 0;
++  mCurrentInLine = 0;
++  mLinesInBuffer = 0;
++
++  if (mFrameRect.IsEmpty()) {
++    // Our frame rect is zero size; commit rows until the end of the image.
++    SkipToRow(mOriginalSize.height - 1);
++  } else {
++    // If we have a vertical offset, commit rows to shift us past it.
++    SkipToRow(mFrameRect.y);
++  }
++}
++
++static void
++GetFilterOffsetAndLength(UniquePtr<skia::ConvolutionFilter1D>& aFilter,
++                         int32_t aOutputImagePosition,
++                         int32_t* aFilterOffsetOut,
++                         int32_t* aFilterLengthOut)
++{
++  MOZ_ASSERT(aOutputImagePosition < aFilter->num_values());
++  aFilter->FilterForValue(aOutputImagePosition,
++                          aFilterOffsetOut,
++                          aFilterLengthOut);
++}
++
++void
++Downscaler::ClearRow(uint32_t aStartingAtCol)
++{
++  MOZ_ASSERT(int64_t(mOriginalSize.width) > int64_t(aStartingAtCol));
++  uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
++                        * sizeof(uint32_t);
++  memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
++         0, bytesToClear);
++}
++
++void
++Downscaler::CommitRow()
++{
++  MOZ_ASSERT(mOutputBuffer, "Should have a current frame");
++  MOZ_ASSERT(mCurrentInLine < mOriginalSize.height, "Past end of input");
++
++  if (mCurrentOutLine < mTargetSize.height) {
++    int32_t filterOffset = 0;
++    int32_t filterLength = 0;
++    GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
++                             &filterOffset, &filterLength);
++
++    int32_t inLineToRead = filterOffset + mLinesInBuffer;
++    MOZ_ASSERT(mCurrentInLine <= inLineToRead, "Reading past end of input");
++    if (mCurrentInLine == inLineToRead) {
++      skia::ConvolveHorizontally(mRowBuffer.get(), *mXFilter,
++                                 mWindow[mLinesInBuffer++], mHasAlpha,
++                                 supports_sse2());
++    }
++
++    MOZ_ASSERT(mCurrentOutLine < mTargetSize.height,
++               "Writing past end of output");
++
++    while (mLinesInBuffer == filterLength) {
++      DownscaleInputLine();
++
++      if (mCurrentOutLine == mTargetSize.height) {
++        break;  // We're done.
++      }
++
++      GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
++                               &filterOffset, &filterLength);
++    }
++  }
++
++  mCurrentInLine += 1;
++
++  // If we're at the end of the part of the original image that has data, commit
++  // rows to shift us to the end.
++  if (mCurrentInLine == (mFrameRect.y + mFrameRect.height)) {
++    SkipToRow(mOriginalSize.height - 1);
++  }
++}
++
++bool
++Downscaler::HasInvalidation() const
++{
++  return mCurrentOutLine > mPrevInvalidatedLine;
++}
++
++DownscalerInvalidRect
++Downscaler::TakeInvalidRect()
++{
++  if (MOZ_UNLIKELY(!HasInvalidation())) {
++    return DownscalerInvalidRect();
++  }
++
++  DownscalerInvalidRect invalidRect;
++
++  // Compute the target size invalid rect.
++  if (mFlipVertically) {
++    // We need to flip it. This will implicitly flip the original size invalid
++    // rect, since we compute it by scaling this rect.
++    invalidRect.mTargetSizeRect =
++      IntRect(0, mTargetSize.height - mCurrentOutLine,
++              mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
++  } else {
++    invalidRect.mTargetSizeRect =
++      IntRect(0, mPrevInvalidatedLine,
++              mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
++  }
++
++  mPrevInvalidatedLine = mCurrentOutLine;
++
++  // Compute the original size invalid rect.
++  invalidRect.mOriginalSizeRect = invalidRect.mTargetSizeRect;
++  invalidRect.mOriginalSizeRect.ScaleRoundOut(mScale.width, mScale.height);
++
++  return invalidRect;
++}
++
++void
++Downscaler::DownscaleInputLine()
++{
++  typedef skia::ConvolutionFilter1D::Fixed FilterValue;
++
++  MOZ_ASSERT(mOutputBuffer);
++  MOZ_ASSERT(mCurrentOutLine < mTargetSize.height,
++             "Writing past end of output");
++
++  int32_t filterOffset = 0;
++  int32_t filterLength = 0;
++  MOZ_ASSERT(mCurrentOutLine < mYFilter->num_values());
++  auto filterValues =
++    mYFilter->FilterForValue(mCurrentOutLine, &filterOffset, &filterLength);
++
++  int32_t currentOutLine = mFlipVertically
++                         ? mTargetSize.height - (mCurrentOutLine + 1)
++                         : mCurrentOutLine;
++  MOZ_ASSERT(currentOutLine >= 0);
++
++  uint8_t* outputLine =
++    &mOutputBuffer[currentOutLine * mTargetSize.width * sizeof(uint32_t)];
++  skia::ConvolveVertically(static_cast<const FilterValue*>(filterValues),
++                           filterLength, mWindow.get(), mXFilter->num_values(),
++                           outputLine, mHasAlpha, supports_sse2());
++
++  mCurrentOutLine += 1;
++
++  if (mCurrentOutLine == mTargetSize.height) {
++    // We're done.
++    return;
++  }
++
++  int32_t newFilterOffset = 0;
++  int32_t newFilterLength = 0;
++  GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
++                           &newFilterOffset, &newFilterLength);
++
++  int diff = newFilterOffset - filterOffset;
++  MOZ_ASSERT(diff >= 0, "Moving backwards in the filter?");
++
++  // Shift the buffer. We're just moving pointers here, so this is cheap.
++  mLinesInBuffer -= diff;
++  mLinesInBuffer = max(mLinesInBuffer, 0);
++  for (int32_t i = 0; i < mLinesInBuffer; ++i) {
++    swap(mWindow[i], mWindow[filterLength - mLinesInBuffer + i]);
++  }
++}
++
++
++
++} // namespace image
++} // namespace mozilla
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch
new file mode 100644
index 0000000000..e01b5eaf2f
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch
@@ -0,0 +1,58 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/9719b71d72dd
+
+# HG changeset patch
+# User Byron Campen [:bwc] <docfaraday@gmail.com>
+# Date 1454100887 21600
+# Node ID 9719b71d72dd2a3c5ee12ace156af2a63d9595ac
+# Parent  b68673d974a10f65390f80b36d4307eb31e44669
+Bug 1234578 - Assert if PCM is destroyed improperly. r=rjesup, a=sylvestre
+
+diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
++++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+@@ -712,16 +712,18 @@ PeerConnectionMedia::SelfDestruct_m()
+ {
+   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
+ 
+   ASSERT_ON_THREAD(mMainThread);
+ 
+   mLocalSourceStreams.Clear();
+   mRemoteSourceStreams.Clear();
+ 
++  mMainThread = nullptr;
++
+   // Final self-destruct.
+   this->Release();
+ }
+ 
+ void
+ PeerConnectionMedia::ShutdownMediaTransport_s()
+ {
+   ASSERT_ON_THREAD(mSTSThread);
+diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
++++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+@@ -210,17 +210,20 @@ class RemoteSourceStreamInfo : public So
+   std::vector<std::string> mTrackIdMap;
+ 
+   // True iff SetPullEnabled(true) has been called on the DOMMediaStream. This
+   // happens when offer/answer concludes.
+   bool mReceiving;
+ };
+ 
+ class PeerConnectionMedia : public sigslot::has_slots<> {
+-  ~PeerConnectionMedia() {}
++  ~PeerConnectionMedia()
++  {
++    MOZ_RELEASE_ASSERT(!mMainThread);
++  }
+ 
+  public:
+   explicit PeerConnectionMedia(PeerConnectionImpl *parent);
+ 
+   PeerConnectionImpl* GetPC() { return mParent; }
+   nsresult Init(const std::vector<NrIceStunServer>& stun_servers,
+                 const std::vector<NrIceTurnServer>& turn_servers);
+   // WARNING: This destroys the object!
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch
new file mode 100644
index 0000000000..96b83c118c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch
@@ -0,0 +1,60 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/2839062f84fb
+
+# HG changeset patch
+# User Jan de Mooij <jdemooij@mozilla.com>
+# Date 1455119320 -3600
+# Node ID 2839062f84fb6cba2781ea8d59150f13d4813ddc
+# Parent  185b233ea03f3811404e3979b65ec86b29d13555
+Bug 1242279 - r=bhackett1024 a=sylvestre
+
+diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
+--- a/js/src/vm/TypeInference.cpp
++++ b/js/src/vm/TypeInference.cpp
+@@ -3961,16 +3961,22 @@ JSScript::maybeSweepTypes(AutoClearTypeI
+ 
+     unsigned num = TypeScript::NumTypeSets(this);
+     StackTypeSet* typeArray = types_->typeArray();
+ 
+     // Remove constraints and references to dead objects from stack type sets.
+     for (unsigned i = 0; i < num; i++)
+         typeArray[i].sweep(zone(), *oom);
+ 
++    if (oom->hadOOM()) {
++        // It's possible we OOM'd while copying freeze constraints, so they
++        // need to be regenerated.
++        hasFreezeConstraints_ = false;
++    }
++
+     // Update the recompile indexes in any IonScripts still on the script.
+     if (hasIonScript())
+         ionScript()->recompileInfoRef().shouldSweep(types);
+ }
+ 
+ void
+ TypeScript::destroy()
+ {
+diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h
+--- a/js/src/vm/TypeInference.h
++++ b/js/src/vm/TypeInference.h
+@@ -566,16 +566,19 @@ class AutoClearTypeInferenceStateOnOOM
+       : zone(zone), oom(false)
+     {}
+ 
+     ~AutoClearTypeInferenceStateOnOOM();
+ 
+     void setOOM() {
+         oom = true;
+     }
++    bool hadOOM() const {
++        return oom;
++    }
+ };
+ 
+ /* Superclass common to stack and heap type sets. */
+ class ConstraintTypeSet : public TypeSet
+ {
+   public:
+     /* Chain of constraints which propagate changes out from this type set. */
+     TypeConstraint* constraintList;
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch
new file mode 100644
index 0000000000..4eeb2377b0
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch
@@ -0,0 +1,53 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/9dd60e798819
+
+# HG changeset patch
+# User Olli Pettay <bugs@pettay.fi>
+# Date 1455204078 -3600
+# Node ID 9dd60e798819fe2ebf1e5bd36aa9006ecd2f82c9
+# Parent  c1d67bd4c993b9e344c68954e6f0392c82b81e38
+Bug 1244250 - r=mats, a=al
+
+diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp
+--- a/layout/style/nsAnimationManager.cpp
++++ b/layout/style/nsAnimationManager.cpp
+@@ -715,16 +715,17 @@ nsAnimationManager::FlushAnimations(Flus
+   }
+ 
+   DispatchEvents(); // may destroy us
+ }
+ 
+ void
+ nsAnimationManager::DoDispatchEvents()
+ {
++  nsRefPtr<nsAnimationManager> kungFuDeathGrip(this);
+   EventArray events;
+   mPendingEvents.SwapElements(events);
+   for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) {
+     AnimationEventInfo &info = events[i];
+     EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
+ 
+     if (!mPresContext) {
+       break;
+diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp
+--- a/layout/style/nsTransitionManager.cpp
++++ b/layout/style/nsTransitionManager.cpp
+@@ -753,16 +753,17 @@ nsTransitionManager::FlushTransitions(Fl
+       }
+     }
+   }
+ 
+   if (didThrottle) {
+     mPresContext->Document()->SetNeedStyleFlush();
+   }
+ 
++  nsRefPtr<nsTransitionManager> kungFuDeathGrip(this);
+   for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) {
+     TransitionEventInfo &info = events[i];
+     EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
+ 
+     if (!mPresContext) {
+       break;
+     }
+   }
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch
new file mode 100644
index 0000000000..d222feff2a
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch
@@ -0,0 +1,32 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/1dd0ca8e70bd
+
+# HG changeset patch
+# User Nicolas B. Pierron <nicolas.b.pierron@mozilla.com>
+# Date 1456161361 0
+# Node ID 1dd0ca8e70bd77b6fd93f36cc4e9c2cebfe8ba0a
+# Parent  95ff874886905ef46a7bbc760981d15ad0831096
+Bug 1221872 - ValueNumbering: Set the dominator index of fixup blocks when they are created. r=sunfish, a=ritu
+
+diff --git a/js/src/jit/ValueNumbering.cpp b/js/src/jit/ValueNumbering.cpp
+--- a/js/src/jit/ValueNumbering.cpp
++++ b/js/src/jit/ValueNumbering.cpp
+@@ -433,16 +433,17 @@ ValueNumberer::fixupOSROnlyLoop(MBasicBl
+     MBasicBlock* fake = MBasicBlock::NewAsmJS(graph_, block->info(),
+                                               nullptr, MBasicBlock::NORMAL);
+     if (fake == nullptr)
+         return false;
+ 
+     graph_.insertBlockBefore(block, fake);
+     fake->setImmediateDominator(fake);
+     fake->addNumDominated(1);
++    fake->setDomIndex(fake->id());
+ 
+     // Create zero-input phis to use as inputs for any phis in |block|.
+     // Again, this is a little odd, but it's the least-odd thing we can do
+     // without significant complexity.
+     for (MPhiIterator iter(block->phisBegin()), end(block->phisEnd()); iter != end; ++iter) {
+         MPhi* phi = *iter;
+         MPhi* fakePhi = MPhi::New(graph_.alloc(), phi->type());
+         fake->addPhi(fakePhi);
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch
new file mode 100644
index 0000000000..3de568493b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch
@@ -0,0 +1,103 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/6f4d51302387
+
+# HG changeset patch
+# User Andrew McCreight <continuation@gmail.com>
+# Date 1456273423 28800
+# Node ID 6f4d5130238790fa5810c76ffeb9eccc65efa8c9
+# Parent  70f6c59d9d73a5edefd216b48ca74a931da12cf1
+Bug 1249685 - Use more nsCOMPtrs for stack variables in DOM code. r=smaug, a=ritu
+
+diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp
+--- a/dom/base/nsRange.cpp
++++ b/dom/base/nsRange.cpp
+@@ -1985,17 +1985,17 @@ nsRange::CutContents(DocumentFragment** 
+       rv = closestAncestor ? PrependChild(closestAncestor, nodeToResult)
+                            : PrependChild(commonCloneAncestor, nodeToResult);
+       NS_ENSURE_SUCCESS(rv, rv);
+       NS_ENSURE_STATE(!guard.Mutated(parent ? 2 : 1) ||
+                       ValidateCurrentNode(this, iter));
+     } else if (nodeToResult) {
+       nsMutationGuard guard;
+       nsCOMPtr<nsINode> node = nodeToResult;
+-      nsINode* parent = node->GetParentNode();
++      nsCOMPtr<nsINode> parent = node->GetParentNode();
+       if (parent) {
+         mozilla::ErrorResult error;
+         parent->RemoveChild(*node, error);
+         NS_ENSURE_FALSE(error.Failed(), error.ErrorCode());
+       }
+       NS_ENSURE_STATE(!guard.Mutated(1) ||
+                       ValidateCurrentNode(this, iter));
+     }
+diff --git a/dom/base/nsTreeSanitizer.cpp b/dom/base/nsTreeSanitizer.cpp
+--- a/dom/base/nsTreeSanitizer.cpp
++++ b/dom/base/nsTreeSanitizer.cpp
+@@ -1423,18 +1423,18 @@ nsTreeSanitizer::SanitizeChildren(nsINod
+                              mAllowStyles,
+                              false);
+         }
+         node = node->GetNextNonChildNode(aRoot);
+         continue;
+       }
+       if (MustFlatten(ns, localName)) {
+         RemoveAllAttributes(node);
+-        nsIContent* next = node->GetNextNode(aRoot);
+-        nsIContent* parent = node->GetParent();
++        nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
++        nsCOMPtr<nsIContent> parent = node->GetParent();
+         nsCOMPtr<nsIContent> child; // Must keep the child alive during move
+         ErrorResult rv;
+         while ((child = node->GetFirstChild())) {
+           parent->InsertBefore(*child, node, rv);
+           if (rv.Failed()) {
+             break;
+           }
+         }
+diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp
+--- a/dom/html/HTMLSelectElement.cpp
++++ b/dom/html/HTMLSelectElement.cpp
+@@ -624,17 +624,17 @@ HTMLSelectElement::Add(nsGenericHTMLElem
+ {
+   if (!aBefore) {
+     Element::AppendChild(aElement, aError);
+     return;
+   }
+ 
+   // Just in case we're not the parent, get the parent of the reference
+   // element
+-  nsINode* parent = aBefore->Element::GetParentNode();
++  nsCOMPtr<nsINode> parent = aBefore->Element::GetParentNode();
+   if (!parent || !nsContentUtils::ContentIsDescendantOf(parent, this)) {
+     // NOT_FOUND_ERR: Raised if before is not a descendant of the SELECT
+     // element.
+     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
+     return;
+   }
+ 
+   // If the before parameter is not null, we are equivalent to the
+diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp
+--- a/dom/html/HTMLTableElement.cpp
++++ b/dom/html/HTMLTableElement.cpp
+@@ -516,18 +516,18 @@ HTMLTableElement::InsertRow(int32_t aInd
+   if (rowCount > 0) {
+     if (refIndex == rowCount || aIndex == -1) {
+       // we set refIndex to the last row so we can get the last row's
+       // parent we then do an AppendChild below if (rowCount<aIndex)
+ 
+       refIndex = rowCount - 1;
+     }
+ 
+-    Element* refRow = rows->Item(refIndex);
+-    nsINode* parent = refRow->GetParentNode();
++    RefPtr<Element> refRow = rows->Item(refIndex);
++    nsCOMPtr<nsINode> parent = refRow->GetParentNode();
+ 
+     // create the row
+     nsRefPtr<mozilla::dom::NodeInfo> nodeInfo;
+     nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::tr,
+                                 getter_AddRefs(nodeInfo));
+ 
+     newRow = NS_NewHTMLTableRowElement(nodeInfo.forget());
+ 
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1954.patch b/gnu/packages/patches/icecat-CVE-2016-1954.patch
new file mode 100644
index 0000000000..bbb4b3217c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1954.patch
@@ -0,0 +1,32 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/a5c4c18849b4
+
+# HG changeset patch
+# User Christoph Kerschbaumer <mozilla@christophkerschbaumer.com>
+# Date 1456157874 28800
+# Node ID a5c4c18849b486ef8693e20421b69239a2cbe574
+# Parent  e93aeb25e2a44df8d22f5a065b4410620e2c8730
+Bug 1243178: CSP - Skip sending reports for non http schemes (r=dveditz) a=ritu
+
+diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp
+--- a/dom/security/nsCSPContext.cpp
++++ b/dom/security/nsCSPContext.cpp
+@@ -798,16 +798,17 @@ nsCSPContext::SendReports(nsISupports* a
+       (NS_SUCCEEDED(reportURI->SchemeIs("https", &isHttpScheme)) && isHttpScheme);
+ 
+     if (!isHttpScheme) {
+       const char16_t* params[] = { reportURIs[r].get() };
+       CSP_LogLocalizedStr(NS_LITERAL_STRING("reportURInotHttpsOrHttp2").get(),
+                           params, ArrayLength(params),
+                           aSourceFile, aScriptSample, aLineNum, 0,
+                           nsIScriptError::errorFlag, "CSP", mInnerWindowID);
++      continue;
+     }
+ 
+     // make sure this is an anonymous request (no cookies) so in case the
+     // policy URI is injected, it can't be abused for CSRF.
+     nsLoadFlags flags;
+     rv = reportChannel->GetLoadFlags(&flags);
+     NS_ENSURE_SUCCESS(rv, rv);
+     flags |= nsIRequest::LOAD_ANONYMOUS;
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1960.patch b/gnu/packages/patches/icecat-CVE-2016-1960.patch
new file mode 100644
index 0000000000..6c5c885e8b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1960.patch
@@ -0,0 +1,55 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/185b233ea03f
+
+# HG changeset patch
+# User Henri Sivonen <hsivonen@hsivonen.fi>
+# Date 1455100746 -7200
+# Node ID 185b233ea03f3811404e3979b65ec86b29d13555
+# Parent  271e3a5a53d96871141e89271f611033b512e3e4
+Bug 1246014. r=wchen. a=sylvestre
+
+diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java
+--- a/parser/html/javasrc/TreeBuilder.java
++++ b/parser/html/javasrc/TreeBuilder.java
+@@ -4437,17 +4437,17 @@ public abstract class TreeBuilder<T> imp
+         return TreeBuilder.NOT_FOUND_ON_STACK;
+     }
+ 
+     private void clearStackBackTo(int eltPos) throws SAXException {
+         int eltGroup = stack[eltPos].getGroup();
+         while (currentPtr > eltPos) { // > not >= intentional
+             if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml"
+                     && stack[currentPtr].getGroup() == TEMPLATE
+-                    && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltGroup == HTML)) {
++                    && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltPos == 0)) {
+                 return;
+             }
+             pop();
+         }
+     }
+ 
+     private void resetTheInsertionMode() {
+         StackNode<T> node;
+diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp
+--- a/parser/html/nsHtml5TreeBuilder.cpp
++++ b/parser/html/nsHtml5TreeBuilder.cpp
+@@ -3301,17 +3301,17 @@ nsHtml5TreeBuilder::findLastInTableScope
+   return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
+ }
+ 
+ void 
+ nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos)
+ {
+   int32_t eltGroup = stack[eltPos]->getGroup();
+   while (currentPtr > eltPos) {
+-    if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE && (eltGroup == NS_HTML5TREE_BUILDER_TABLE || eltGroup == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || eltGroup == NS_HTML5TREE_BUILDER_TR || eltGroup == NS_HTML5TREE_BUILDER_HTML)) {
++    if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE && (eltGroup == NS_HTML5TREE_BUILDER_TABLE || eltGroup == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || eltGroup == NS_HTML5TREE_BUILDER_TR || !eltPos)) {
+       return;
+     }
+     pop();
+   }
+ }
+ 
+ void 
+ nsHtml5TreeBuilder::resetTheInsertionMode()
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1961.patch b/gnu/packages/patches/icecat-CVE-2016-1961.patch
new file mode 100644
index 0000000000..10162be24b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1961.patch
@@ -0,0 +1,33 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/e93aeb25e2a4
+
+# HG changeset patch
+# User Andrew McCreight <continuation@gmail.com>
+# Date 1455891967 28800
+# Node ID e93aeb25e2a44df8d22f5a065b4410620e2c8730
+# Parent  221de852fda32714a9e484774ceafafb450ea73c
+Bug 1249377 - Hold a strong reference to |root| in nsHTMLDocument::SetBody. r=bz, a=sylvestre
+
+diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
+--- a/dom/html/nsHTMLDocument.cpp
++++ b/dom/html/nsHTMLDocument.cpp
+@@ -1044,17 +1044,17 @@ nsHTMLDocument::SetBody(nsIDOMHTMLElemen
+   ErrorResult rv;
+   SetBody(static_cast<nsGenericHTMLElement*>(newBody.get()), rv);
+   return rv.ErrorCode();
+ }
+ 
+ void
+ nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
+ {
+-  Element* root = GetRootElement();
++  nsCOMPtr<Element> root = GetRootElement();
+ 
+   // The body element must be either a body tag or a frameset tag. And we must
+   // have a html root tag, otherwise GetBody will not return the newly set
+   // body.
+   if (!newBody || !(newBody->Tag() == nsGkAtoms::body ||
+                     newBody->Tag() == nsGkAtoms::frameset) ||
+       !root || !root->IsHTML() ||
+       root->Tag() != nsGkAtoms::html) {
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1962.patch b/gnu/packages/patches/icecat-CVE-2016-1962.patch
new file mode 100644
index 0000000000..7eb4e072a1
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1962.patch
@@ -0,0 +1,107 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/221de852fda3
+
+# HG changeset patch
+# User Randell Jesup <rjesup@jesup.org>
+# Date 1455862087 18000
+# Node ID 221de852fda32714a9e484774ceafafb450ea73c
+# Parent  b03db72e32f6e3acdc9f8705371cb222d7e6c456
+Bug 1240760: Update DataChannel::Close() r=mcmanus, a=ritu
+
+MozReview-Commit-ID: 7nN9h3M3O8w
+
+diff --git a/netwerk/sctp/datachannel/DataChannel.cpp b/netwerk/sctp/datachannel/DataChannel.cpp
+--- a/netwerk/sctp/datachannel/DataChannel.cpp
++++ b/netwerk/sctp/datachannel/DataChannel.cpp
+@@ -1771,17 +1771,17 @@ DataChannelConnection::HandleStreamReset
+           }
+           NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
+                                     DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
+                                     channel));
+           mStreams[channel->mStream] = nullptr;
+ 
+           LOG(("Disconnected DataChannel %p from connection %p",
+                (void *) channel.get(), (void *) channel->mConnection.get()));
+-          channel->Destroy();
++          channel->DestroyLocked();
+           // At this point when we leave here, the object is a zombie held alive only by the DOM object
+         } else {
+           LOG(("Can't find incoming channel %d",i));
+         }
+       }
+     }
+   }
+ 
+@@ -2498,17 +2498,17 @@ DataChannelConnection::CloseInt(DataChan
+       mStreams[channel->mStream] = nullptr;
+     } else {
+       SendOutgoingStreamReset();
+     }
+   }
+   aChannel->mState = CLOSING;
+   if (mState == CLOSED) {
+     // we're not going to hang around waiting
+-    channel->Destroy();
++    channel->DestroyLocked();
+   }
+   // At this point when we leave here, the object is a zombie held alive only by the DOM object
+ }
+ 
+ void DataChannelConnection::CloseAll()
+ {
+   LOG(("Closing all channels (connection %p)", (void*) this));
+   // Don't need to lock here
+@@ -2552,23 +2552,25 @@ DataChannel::~DataChannel()
+   // wrong, nothing bad happens.  A worst it's a leak.
+   NS_ASSERTION(mState == CLOSED || mState == CLOSING, "unexpected state in ~DataChannel");
+ }
+ 
+ void
+ DataChannel::Close()
+ {
+   ENSURE_DATACONNECTION;
++  RefPtr<DataChannelConnection> connection(mConnection);
+   mConnection->Close(this);
+ }
+ 
+ // Used when disconnecting from the DataChannelConnection
+ void
+-DataChannel::Destroy()
++DataChannel::DestroyLocked()
+ {
++  mConnection->mLock.AssertCurrentThreadOwns();
+   ENSURE_DATACONNECTION;
+ 
+   LOG(("Destroying Data channel %u", mStream));
+   MOZ_ASSERT_IF(mStream != INVALID_STREAM,
+                 !mConnection->FindChannelByStream(mStream));
+   mStream = INVALID_STREAM;
+   mState = CLOSED;
+   mConnection = nullptr;
+diff --git a/netwerk/sctp/datachannel/DataChannel.h b/netwerk/sctp/datachannel/DataChannel.h
+--- a/netwerk/sctp/datachannel/DataChannel.h
++++ b/netwerk/sctp/datachannel/DataChannel.h
+@@ -331,19 +331,20 @@ public:
+     {
+       NS_ASSERTION(mConnection,"NULL connection");
+     }
+ 
+ private:
+   ~DataChannel();
+ 
+ public:
+-  void Destroy(); // when we disconnect from the connection after stream RESET
++  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
+ 
+-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
++  // when we disconnect from the connection after stream RESET
++  void DestroyLocked();
+ 
+   // Close this DataChannel.  Can be called multiple times.  MUST be called
+   // before destroying the DataChannel (state must be CLOSED or CLOSING).
+   void Close();
+ 
+   // Set the listener (especially for channels created from the other side)
+   void SetListener(DataChannelListener *aListener, nsISupports *aContext);
+ 
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1964.patch b/gnu/packages/patches/icecat-CVE-2016-1964.patch
new file mode 100644
index 0000000000..e53fc749b5
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1964.patch
@@ -0,0 +1,54 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/a653013e7b50
+
+# HG changeset patch
+# User Peter Van der Beken <peterv@propagandism.org>
+# Date 1454340035 -3600
+# Node ID a653013e7b503912a32621e8da64a37171316588
+# Parent  0d0d7e8292f7ecf5f1149d528c0524f04447c4ad
+Bug 1243335 - report bad QName. r=sicking, a=sylvestre
+
+diff --git a/dom/xslt/xslt/txInstructions.cpp b/dom/xslt/xslt/txInstructions.cpp
+--- a/dom/xslt/xslt/txInstructions.cpp
++++ b/dom/xslt/xslt/txInstructions.cpp
+@@ -93,16 +93,19 @@ txAttribute::txAttribute(nsAutoPtr<Expr>
+                          txNamespaceMap* aMappings)
+     : mName(Move(aName)), mNamespace(Move(aNamespace)), mMappings(aMappings)
+ {
+ }
+ 
+ nsresult
+ txAttribute::execute(txExecutionState& aEs)
+ {
++    nsAutoPtr<txTextHandler> handler(
++        static_cast<txTextHandler*>(aEs.popResultHandler()));
++
+     nsAutoString name;
+     nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
+     NS_ENSURE_SUCCESS(rv, rv);
+ 
+     const char16_t* colon;
+     if (!XMLUtils::isValidQName(name, &colon) ||
+         TX_StringEqualsAtom(name, nsGkAtoms::xmlns)) {
+         return NS_OK;
+@@ -125,19 +128,16 @@ txAttribute::execute(txExecutionState& a
+         if (!nspace.IsEmpty()) {
+             nsId = txNamespaceManager::getNamespaceID(nspace);
+         }
+     }
+     else if (colon) {
+         nsId = mMappings->lookupNamespace(prefix);
+     }
+ 
+-    nsAutoPtr<txTextHandler> handler(
+-        static_cast<txTextHandler*>(aEs.popResultHandler()));
+-
+     // add attribute if everything was ok
+     return nsId != kNameSpaceID_Unknown ?
+            aEs.mResultHandler->attribute(prefix, Substring(name, lnameStart),
+                                          nsId, handler->mValue) :
+            NS_OK;
+ }
+ 
+ txCallTemplate::txCallTemplate(const txExpandedName& aName)
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1965.patch b/gnu/packages/patches/icecat-CVE-2016-1965.patch
new file mode 100644
index 0000000000..8a37d4975c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1965.patch
@@ -0,0 +1,44 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/b4467681abd6
+
+# HG changeset patch
+# User Gijs Kruitbosch <gijskruitbosch@gmail.com>
+# Date 1455276061 0
+# Node ID b4467681abd676cd5575cbdf922927f8f54d2ad9
+# Parent  8c1d40e45a72c6432e879137a0afa519dc6c9841
+Bug 1245264 - r=bz, r=ritu
+
+MozReview-Commit-ID: I0sVdritpD3
+
+diff --git a/dom/base/nsLocation.cpp b/dom/base/nsLocation.cpp
+--- a/dom/base/nsLocation.cpp
++++ b/dom/base/nsLocation.cpp
+@@ -735,16 +735,27 @@ nsLocation::SetProtocol(const nsAString&
+     return rv;
+   }
+ 
+   rv = uri->SetScheme(NS_ConvertUTF16toUTF8(aProtocol));
+   if (NS_WARN_IF(NS_FAILED(rv))) {
+     return rv;
+   }
+ 
++  nsAutoCString newSpec;
++  rv = uri->GetSpec(newSpec);
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++  // We may want a new URI class for the new URI, so recreate it:
++  rv = NS_NewURI(getter_AddRefs(uri), newSpec);
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++
+   return SetURI(uri);
+ }
+ 
+ void
+ nsLocation::GetUsername(nsAString& aUsername, ErrorResult& aError)
+ {
+   if (!CallerSubsumes()) {
+     aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1966.patch b/gnu/packages/patches/icecat-CVE-2016-1966.patch
new file mode 100644
index 0000000000..6bf5f9f95e
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1966.patch
@@ -0,0 +1,36 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/291c2f31c48c
+
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1454650565 -39600
+# Node ID 291c2f31c48c7e96b1884b55273355970fa0fc30
+# Parent  11e6614756551cfd7291e73eefb90c52873a8480
+Bug 1246054 - Fix an erroneous nsNPObjWrapper assertion. r=froydnj. a=ritu
+
+diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp
+--- a/dom/plugins/base/nsJSNPRuntime.cpp
++++ b/dom/plugins/base/nsJSNPRuntime.cpp
+@@ -1915,18 +1915,19 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
+   // No existing JSObject, create one.
+ 
+   JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, js::Jsvalify(&sNPObjectJSWrapperClass)));
+ 
+   if (generation != sNPObjWrappers.Generation()) {
+       // Reload entry if the JS_NewObject call caused a GC and reallocated
+       // the table (see bug 445229). This is guaranteed to succeed.
+ 
+-      NS_ASSERTION(PL_DHashTableSearch(&sNPObjWrappers, npobj),
+-                   "Hashtable didn't find what we just added?");
++      entry = static_cast<NPObjWrapperHashEntry*>
++        (PL_DHashTableSearch(&sNPObjWrappers, npobj));
++      NS_ASSERTION(entry, "Hashtable didn't find what we just added?");
+   }
+ 
+   if (!obj) {
+     // OOM? Remove the stale entry from the hash.
+ 
+     PL_DHashTableRawRemove(&sNPObjWrappers, entry);
+ 
+     return nullptr;
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1974.patch b/gnu/packages/patches/icecat-CVE-2016-1974.patch
new file mode 100644
index 0000000000..70fc23b8f3
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1974.patch
@@ -0,0 +1,530 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/271e3a5a53d9
+
+# HG changeset patch
+# User Henri Sivonen <hsivonen@hsivonen.fi>
+# Date 1455014759 -7200
+# Node ID 271e3a5a53d96871141e89271f611033b512e3e4
+# Parent  9719b71d72dd2a3c5ee12ace156af2a63d9595ac
+Bug 1228103. r=smaug. a=sylvestre
+
+diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp
+--- a/parser/htmlparser/nsExpatDriver.cpp
++++ b/parser/htmlparser/nsExpatDriver.cpp
+@@ -1127,22 +1127,28 @@ nsExpatDriver::ConsumeToken(nsScanner& a
+       XML_Size lastLineLength = XML_GetCurrentColumnNumber(mExpatParser);
+ 
+       if (lastLineLength <= consumed) {
+         // The length of the last line was less than what expat consumed, so
+         // there was at least one line break in the consumed data. Store the
+         // last line until the point where we stopped parsing.
+         nsScannerIterator startLastLine = currentExpatPosition;
+         startLastLine.advance(-((ptrdiff_t)lastLineLength));
+-        CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine);
++        if (!CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine)) {
++          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
++        }
+       }
+       else {
+         // There was no line break in the consumed data, append the consumed
+         // data.
+-        AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine);
++        if (!AppendUnicodeTo(oldExpatPosition,
++                             currentExpatPosition,
++                             mLastLine)) {
++          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
++        }
+       }
+     }
+ 
+     mExpatBuffered += length - consumed;
+ 
+     if (BlockedOrInterrupted()) {
+       PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
+              ("Blocked or interrupted parser (probably for loading linked "
+diff --git a/parser/htmlparser/nsParser.cpp b/parser/htmlparser/nsParser.cpp
+--- a/parser/htmlparser/nsParser.cpp
++++ b/parser/htmlparser/nsParser.cpp
+@@ -1508,17 +1508,19 @@ nsParser::ResumeParse(bool allowIteratio
+                 DidBuildModel(mStreamStatus);
+                 return NS_OK;
+               }
+             } else {
+               CParserContext* theContext = PopContext();
+               if (theContext) {
+                 theIterationIsOk = allowIteration && theContextIsStringBased;
+                 if (theContext->mCopyUnused) {
+-                  theContext->mScanner->CopyUnusedData(mUnusedInput);
++                  if (!theContext->mScanner->CopyUnusedData(mUnusedInput)) {
++                    mInternalState = NS_ERROR_OUT_OF_MEMORY;
++                  }
+                 }
+ 
+                 delete theContext;
+               }
+ 
+               result = mInternalState;
+               aIsFinalChunk = mParserContext &&
+                               mParserContext->mStreamListenerState == eOnStop;
+diff --git a/parser/htmlparser/nsScanner.cpp b/parser/htmlparser/nsScanner.cpp
+--- a/parser/htmlparser/nsScanner.cpp
++++ b/parser/htmlparser/nsScanner.cpp
+@@ -379,17 +379,19 @@ nsresult nsScanner::Peek(nsAString& aStr
+   if (mCountRemaining < uint32_t(aNumChars + aOffset)) {
+     end = mEndPosition;
+   }
+   else {
+     end = start;
+     end.advance(aNumChars);
+   }
+ 
+-  CopyUnicodeTo(start, end, aStr);
++  if (!CopyUnicodeTo(start, end, aStr)) {
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
+ 
+   return NS_OK;
+ }
+ 
+ 
+ /**
+  *  Skip whitespace on scanner input stream
+  *  
+@@ -542,17 +544,19 @@ nsresult nsScanner::ReadTagIdentifier(ns
+ 
+     if (!found) {
+       ++current;
+     }
+   }
+ 
+   // Don't bother appending nothing.
+   if (current != mCurrentPosition) {
+-    AppendUnicodeTo(mCurrentPosition, current, aString);
++    if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
++      return NS_ERROR_OUT_OF_MEMORY;
++    }
+   }
+ 
+   SetPosition(current);  
+   if (current == end) {
+     result = kEOF;
+   }
+ 
+   //DoErrTest(aString);
+@@ -597,26 +601,30 @@ nsresult nsScanner::ReadEntityIdentifier
+         default:
+           found = ('a'<=theChar && theChar<='z') ||
+                   ('A'<=theChar && theChar<='Z') ||
+                   ('0'<=theChar && theChar<='9');
+           break;
+       }
+ 
+       if(!found) {
+-        AppendUnicodeTo(mCurrentPosition, current, aString);
++        if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
++          return NS_ERROR_OUT_OF_MEMORY;
++        }
+         break;
+       }
+     }
+     ++current;
+   }
+   
+   SetPosition(current);
+   if (current == end) {
+-    AppendUnicodeTo(origin, current, aString);
++    if (!AppendUnicodeTo(origin, current, aString)) {
++      return NS_ERROR_OUT_OF_MEMORY;
++    }
+     return kEOF;
+   }
+ 
+   //DoErrTest(aString);
+ 
+   return result;
+ }
+ 
+@@ -646,26 +654,30 @@ nsresult nsScanner::ReadNumber(nsString&
+   while(current != end) {
+     theChar=*current;
+     if(theChar) {
+       done = (theChar < '0' || theChar > '9') && 
+              ((aBase == 16)? (theChar < 'A' || theChar > 'F') &&
+                              (theChar < 'a' || theChar > 'f')
+                              :true);
+       if(done) {
+-        AppendUnicodeTo(origin, current, aString);
++        if (!AppendUnicodeTo(origin, current, aString)) {
++          return NS_ERROR_OUT_OF_MEMORY;
++        }
+         break;
+       }
+     }
+     ++current;
+   }
+ 
+   SetPosition(current);
+   if (current == end) {
+-    AppendUnicodeTo(origin, current, aString);
++    if (!AppendUnicodeTo(origin, current, aString)) {
++      return NS_ERROR_OUT_OF_MEMORY;
++    }
+     return kEOF;
+   }
+ 
+   //DoErrTest(aString);
+ 
+   return result;
+ }
+ 
+@@ -712,37 +724,43 @@ nsresult nsScanner::ReadWhitespace(nsSca
+           char16_t thePrevChar = theChar;
+           theChar = (++current != end) ? *current : '\0';
+           if ((thePrevChar == '\r' && theChar == '\n') ||
+               (thePrevChar == '\n' && theChar == '\r')) {
+             theChar = (++current != end) ? *current : '\0'; // CRLF == LFCR => LF
+             haveCR = true;
+           } else if (thePrevChar == '\r') {
+             // Lone CR becomes CRLF; callers should know to remove extra CRs
+-            AppendUnicodeTo(origin, current, aString);
++            if (!AppendUnicodeTo(origin, current, aString)) {
++              return NS_ERROR_OUT_OF_MEMORY;
++            }
+             aString.writable().Append(char16_t('\n'));
+             origin = current;
+             haveCR = true;
+           }
+         }
+         break;
+       case ' ' :
+       case '\t':
+         theChar = (++current != end) ? *current : '\0';
+         break;
+       default:
+         done = true;
+-        AppendUnicodeTo(origin, current, aString);
++        if (!AppendUnicodeTo(origin, current, aString)) {
++          return NS_ERROR_OUT_OF_MEMORY;
++        }
+         break;
+     }
+   }
+ 
+   SetPosition(current);
+   if (current == end) {
+-    AppendUnicodeTo(origin, current, aString);
++    if (!AppendUnicodeTo(origin, current, aString)) {
++      return NS_ERROR_OUT_OF_MEMORY;
++    }
+     result = kEOF;
+   }
+ 
+   aHaveCR = haveCR;
+   return result;
+ }
+ 
+ //XXXbz callers of this have to manage their lone '\r' themselves if they want
+@@ -846,34 +864,38 @@ nsresult nsScanner::ReadUntil(nsAString&
+     if(!(theChar & aEndCondition.mFilter)) {
+       // They were. Do a thorough check.
+ 
+       setcurrent = setstart;
+       while (*setcurrent) {
+         if (*setcurrent == theChar) {
+           if(addTerminal)
+             ++current;
+-          AppendUnicodeTo(origin, current, aString);
++          if (!AppendUnicodeTo(origin, current, aString)) {
++            return NS_ERROR_OUT_OF_MEMORY;
++          }
+           SetPosition(current);
+ 
+           //DoErrTest(aString);
+ 
+           return NS_OK;
+         }
+         ++setcurrent;
+       }
+     }
+     
+     ++current;
+   }
+ 
+   // If we are here, we didn't find any terminator in the string and
+   // current = mEndPosition
+   SetPosition(current);
+-  AppendUnicodeTo(origin, current, aString);
++  if (!AppendUnicodeTo(origin, current, aString)) {
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
+   return kEOF;
+ }
+ 
+ nsresult nsScanner::ReadUntil(nsScannerSharedSubstring& aString,
+                               const nsReadEndCondition& aEndCondition,
+                               bool addTerminal)
+ {  
+   if (!mSlidingBuffer) {
+@@ -906,34 +928,38 @@ nsresult nsScanner::ReadUntil(nsScannerS
+     if(!(theChar & aEndCondition.mFilter)) {
+       // They were. Do a thorough check.
+ 
+       setcurrent = setstart;
+       while (*setcurrent) {
+         if (*setcurrent == theChar) {
+           if(addTerminal)
+             ++current;
+-          AppendUnicodeTo(origin, current, aString);
++          if (!AppendUnicodeTo(origin, current, aString)) {
++            return NS_ERROR_OUT_OF_MEMORY;
++          }
+           SetPosition(current);
+ 
+           //DoErrTest(aString);
+ 
+           return NS_OK;
+         }
+         ++setcurrent;
+       }
+     }
+     
+     ++current;
+   }
+ 
+   // If we are here, we didn't find any terminator in the string and
+   // current = mEndPosition
+   SetPosition(current);
+-  AppendUnicodeTo(origin, current, aString);
++  if (!AppendUnicodeTo(origin, current, aString)) {
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
+   return kEOF;
+ }
+ 
+ nsresult nsScanner::ReadUntil(nsScannerIterator& aStart, 
+                               nsScannerIterator& aEnd,
+                               const nsReadEndCondition &aEndCondition,
+                               bool addTerminal)
+ {
+@@ -1025,26 +1051,30 @@ nsresult nsScanner::ReadUntil(nsAString&
+     if (theChar == '\0') {
+       ReplaceCharacter(current, sInvalid);
+       theChar = sInvalid;
+     }
+ 
+     if (aTerminalChar == theChar) {
+       if(addTerminal)
+         ++current;
+-      AppendUnicodeTo(origin, current, aString);
++      if (!AppendUnicodeTo(origin, current, aString)) {
++        return NS_ERROR_OUT_OF_MEMORY;
++      }
+       SetPosition(current);
+       return NS_OK;
+     }
+     ++current;
+   }
+ 
+   // If we are here, we didn't find any terminator in the string and
+   // current = mEndPosition
+-  AppendUnicodeTo(origin, current, aString);
++  if (!AppendUnicodeTo(origin, current, aString)) {
++    return NS_ERROR_OUT_OF_MEMORY;
++  }
+   SetPosition(current);
+   return kEOF;
+ 
+ }
+ 
+ void nsScanner::BindSubstring(nsScannerSubstring& aSubstring, const nsScannerIterator& aStart, const nsScannerIterator& aEnd)
+ {
+   aSubstring.Rebind(*mSlidingBuffer, aStart, aEnd);
+@@ -1142,29 +1172,29 @@ bool nsScanner::AppendToBuffer(nsScanner
+ }
+ 
+ /**
+  *  call this to copy bytes out of the scanner that have not yet been consumed
+  *  by the tokenization process.
+  *  
+  *  @update  gess 5/12/98
+  *  @param   aCopyBuffer is where the scanner buffer will be copied to
+- *  @return  nada
++ *  @return  true if OK or false on OOM
+  */
+-void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
++bool nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
+   if (!mSlidingBuffer) {
+     aCopyBuffer.Truncate();
+-    return;
++    return true;
+   }
+ 
+   nsScannerIterator start, end;
+   start = mCurrentPosition;
+   end = mEndPosition;
+ 
+-  CopyUnicodeTo(start, end, aCopyBuffer);
++  return CopyUnicodeTo(start, end, aCopyBuffer);
+ }
+ 
+ /**
+  *  Retrieve the name of the file that the scanner is reading from.
+  *  In some cases, it's just a given name, because the scanner isn't
+  *  really reading from a file.
+  *  
+  *  @update  gess 5/12/98
+diff --git a/parser/htmlparser/nsScanner.h b/parser/htmlparser/nsScanner.h
+--- a/parser/htmlparser/nsScanner.h
++++ b/parser/htmlparser/nsScanner.h
+@@ -204,19 +204,19 @@ class nsScanner {
+                       nsIRequest *aRequest);
+ 
+       /**
+        *  Call this to copy bytes out of the scanner that have not yet been consumed
+        *  by the tokenization process.
+        *  
+        *  @update  gess 5/12/98
+        *  @param   aCopyBuffer is where the scanner buffer will be copied to
+-       *  @return  nada
++       *  @return  true if OK or false on OOM
+        */
+-      void CopyUnusedData(nsString& aCopyBuffer);
++      bool CopyUnusedData(nsString& aCopyBuffer);
+ 
+       /**
+        *  Retrieve the name of the file that the scanner is reading from.
+        *  In some cases, it's just a given name, because the scanner isn't
+        *  really reading from a file.
+        *  
+        *  @update  gess 5/12/98
+        *  @return  
+diff --git a/parser/htmlparser/nsScannerString.cpp b/parser/htmlparser/nsScannerString.cpp
+--- a/parser/htmlparser/nsScannerString.cpp
++++ b/parser/htmlparser/nsScannerString.cpp
+@@ -461,61 +461,63 @@ copy_multifragment_string( nsScannerIter
+         sink_traits::write(result, source_traits::read(first), distance);
+         NS_ASSERTION(distance > 0, "|copy_multifragment_string| will never terminate");
+         source_traits::advance(first, distance);
+       }
+ 
+     return result;
+   }
+ 
+-void
++bool
+ CopyUnicodeTo( const nsScannerIterator& aSrcStart,
+                const nsScannerIterator& aSrcEnd,
+                nsAString& aDest )
+   {
+     nsAString::iterator writer;
+     if (!aDest.SetLength(Distance(aSrcStart, aSrcEnd), mozilla::fallible)) {
+       aDest.Truncate();
+-      return; // out of memory
++      return false; // out of memory
+     }
+     aDest.BeginWriting(writer);
+     nsScannerIterator fromBegin(aSrcStart);
+     
+     copy_multifragment_string(fromBegin, aSrcEnd, writer);
++    return true;
+   }
+ 
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+                  const nsScannerIterator& aSrcEnd,
+                  nsScannerSharedSubstring& aDest )
+   {
+     // Check whether we can just create a dependent string.
+     if (aDest.str().IsEmpty()) {
+       // We can just make |aDest| point to the buffer.
+       // This will take care of copying if the buffer spans fragments.
+       aDest.Rebind(aSrcStart, aSrcEnd);
+-    } else {
+-      // The dest string is not empty, so it can't be a dependent substring.
+-      AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
++      return true;
+     }
++    // The dest string is not empty, so it can't be a dependent substring.
++    return AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
+   }
+ 
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+                  const nsScannerIterator& aSrcEnd,
+                  nsAString& aDest )
+   {
+     nsAString::iterator writer;
+     uint32_t oldLength = aDest.Length();
+     if (!aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd), mozilla::fallible))
+-      return; // out of memory
++      return false; // out of memory
+     aDest.BeginWriting(writer).advance(oldLength);
+     nsScannerIterator fromBegin(aSrcStart);
+     
+     copy_multifragment_string(fromBegin, aSrcEnd, writer);
++    return true;
+   }
+ 
+ bool
+ FindCharInReadable( char16_t aChar,
+                     nsScannerIterator& aSearchStart,
+                     const nsScannerIterator& aSearchEnd )
+   {
+     while ( aSearchStart != aSearchEnd )
+diff --git a/parser/htmlparser/nsScannerString.h b/parser/htmlparser/nsScannerString.h
+--- a/parser/htmlparser/nsScannerString.h
++++ b/parser/htmlparser/nsScannerString.h
+@@ -539,43 +539,43 @@ nsScannerBufferList::Position::operator=
+ inline
+ size_t
+ Distance( const nsScannerIterator& aStart, const nsScannerIterator& aEnd )
+   {
+     typedef nsScannerBufferList::Position Position;
+     return Position::Distance(Position(aStart), Position(aEnd));
+   }
+ 
+-void
++bool
+ CopyUnicodeTo( const nsScannerIterator& aSrcStart,
+                const nsScannerIterator& aSrcEnd,
+                nsAString& aDest );
+ 
+ inline
+-void
++bool
+ CopyUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
+   {
+     nsScannerIterator begin, end;
+-    CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
++    return CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
+   }
+ 
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+                  const nsScannerIterator& aSrcEnd,
+                  nsAString& aDest );
+ 
+ inline
+-void
++bool
+ AppendUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
+   {
+     nsScannerIterator begin, end;
+-    AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
++    return AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
+   }
+ 
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+                  const nsScannerIterator& aSrcEnd,
+                  nsScannerSharedSubstring& aDest );
+ 
+ bool
+ FindCharInReadable( char16_t aChar,
+                     nsScannerIterator& aStart,
+                     const nsScannerIterator& aEnd );
+
diff --git a/gnu/packages/patches/icecat-bug-1248851.patch b/gnu/packages/patches/icecat-bug-1248851.patch
new file mode 100644
index 0000000000..ea4d6831b5
--- /dev/null
+++ b/gnu/packages/patches/icecat-bug-1248851.patch
@@ -0,0 +1,37 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/8c1d40e45a72
+
+# HG changeset patch
+# User Xidorn Quan <quanxunzhen@gmail.com>
+# Date 1456199544 -28800
+# Node ID 8c1d40e45a72c6432e879137a0afa519dc6c9841
+# Parent  1dd0ca8e70bd77b6fd93f36cc4e9c2cebfe8ba0a
+Bug 1248851 - r=sicking, a=ritu
+
+diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
+--- a/dom/indexedDB/ActorsParent.cpp
++++ b/dom/indexedDB/ActorsParent.cpp
+@@ -14823,22 +14823,19 @@ ObjectStoreAddOrPutRequestOp::DoDatabase
+     }
+ 
+     snappy::RawCompress(uncompressed, uncompressedLength, compressed,
+                         &compressedLength);
+ 
+     uint8_t* dataBuffer = reinterpret_cast<uint8_t*>(compressed);
+     size_t dataBufferLength = compressedLength;
+ 
+-    // If this call succeeds, | compressed | is now owned by the statement, and
+-    // we are no longer responsible for it.
+     rv = stmt->BindAdoptedBlobByName(NS_LITERAL_CSTRING("data"), dataBuffer,
+                                      dataBufferLength);
+     if (NS_WARN_IF(NS_FAILED(rv))) {
+-      moz_free(compressed);
+       return rv;
+     }
+   }
+ 
+   nsCOMPtr<nsIFile> fileDirectory;
+   nsCOMPtr<nsIFile> journalDirectory;
+ 
+   if (mFileManager) {
+