aboutsummaryrefslogtreecommitdiff
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
guix-c3499ad6b8cfdf1c6b09aa51f9f681a5be6c8962.zip
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) {
+