summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2015-05-12 23:18:29 -0400
committerMark H Weaver <mhw@netris.org>2015-05-13 01:32:28 -0400
commite1820d14439abedb1cb1caa5cd9f68bcfcbbd466 (patch)
treea581e61bd8087db71e75e26fd8fe09cc4ba97125
parentd7cbc91d1a81c98b3167603bc1f9405f12a0d6e3 (diff)
downloadguix-e1820d14439abedb1cb1caa5cd9f68bcfcbbd466.tar.gz
guix-e1820d14439abedb1cb1caa5cd9f68bcfcbbd466.tar.xz
gnu: icecat: Apply fixes for CVE-2015-{0797,2708,2710,2713,2716}.
* gnu/packages/patches/icecat-CVE-2015-0797.patch, gnu/packages/patches/icecat-CVE-2015-2708-pt1.patch, gnu/packages/patches/icecat-CVE-2015-2708-pt2.patch, gnu/packages/patches/icecat-CVE-2015-2708-pt3.patch, gnu/packages/patches/icecat-CVE-2015-2708-pt4.patch, gnu/packages/patches/icecat-CVE-2015-2710-pt1.patch, gnu/packages/patches/icecat-CVE-2015-2710-pt2.patch, gnu/packages/patches/icecat-CVE-2015-2710-pt3.patch, gnu/packages/patches/icecat-CVE-2015-2713-pt1.patch, gnu/packages/patches/icecat-CVE-2015-2713-pt2.patch, gnu/packages/patches/icecat-CVE-2015-2716.patch: New files. * gnu-system.am (dist_patch_DATA): Add them. * gnu/packages/gnuzilla.scm (icecat): Add patches.
-rw-r--r--gnu-system.am11
-rw-r--r--gnu/packages/gnuzilla.scm13
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-0797.patch35
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2708-pt1.patch240
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2708-pt2.patch284
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2708-pt3.patch228
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2708-pt4.patch26
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2710-pt1.patch199
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2710-pt2.patch64
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2710-pt3.patch50
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2713-pt1.patch102
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2713-pt2.patch47
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-2716.patch62
13 files changed, 1360 insertions, 1 deletions
diff --git a/gnu-system.am b/gnu-system.am
index d9053bdb7e..e25eae59fe 100644
--- a/gnu-system.am
+++ b/gnu-system.am
@@ -452,6 +452,17 @@ dist_patch_DATA = \
gnu/packages/patches/gtkglext-disable-disable-deprecated.patch \
gnu/packages/patches/hop-bigloo-4.0b.patch \
gnu/packages/patches/hop-linker-flags.patch \
+ gnu/packages/patches/icecat-CVE-2015-0797.patch \
+ gnu/packages/patches/icecat-CVE-2015-2708-pt1.patch \
+ gnu/packages/patches/icecat-CVE-2015-2708-pt2.patch \
+ gnu/packages/patches/icecat-CVE-2015-2708-pt3.patch \
+ gnu/packages/patches/icecat-CVE-2015-2708-pt4.patch \
+ gnu/packages/patches/icecat-CVE-2015-2710-pt1.patch \
+ gnu/packages/patches/icecat-CVE-2015-2710-pt2.patch \
+ gnu/packages/patches/icecat-CVE-2015-2710-pt3.patch \
+ gnu/packages/patches/icecat-CVE-2015-2713-pt1.patch \
+ gnu/packages/patches/icecat-CVE-2015-2713-pt2.patch \
+ gnu/packages/patches/icecat-CVE-2015-2716.patch \
gnu/packages/patches/irrlicht-mesa-10.patch \
gnu/packages/patches/jbig2dec-ignore-testtest.patch \
gnu/packages/patches/kmod-module-directory.patch \
diff --git a/gnu/packages/gnuzilla.scm b/gnu/packages/gnuzilla.scm
index 8031a6c4ce..0207bcbad2 100644
--- a/gnu/packages/gnuzilla.scm
+++ b/gnu/packages/gnuzilla.scm
@@ -233,7 +233,18 @@ standards.")
name "-" version ".tar.bz2"))
(sha256
(base32
- "1a4l23msg4cpc4yp59q2z6xv63r6advlbnjy65v4djv6yhgnqf1i"))))
+ "1a4l23msg4cpc4yp59q2z6xv63r6advlbnjy65v4djv6yhgnqf1i"))
+ (patches (map search-patch '("icecat-CVE-2015-0797.patch"
+ "icecat-CVE-2015-2708-pt1.patch"
+ "icecat-CVE-2015-2708-pt2.patch"
+ "icecat-CVE-2015-2708-pt3.patch"
+ "icecat-CVE-2015-2708-pt4.patch"
+ "icecat-CVE-2015-2710-pt1.patch"
+ "icecat-CVE-2015-2710-pt2.patch"
+ "icecat-CVE-2015-2710-pt3.patch"
+ "icecat-CVE-2015-2713-pt1.patch"
+ "icecat-CVE-2015-2713-pt2.patch"
+ "icecat-CVE-2015-2716.patch")))))
(build-system gnu-build-system)
(inputs
`(("alsa-lib" ,alsa-lib)
diff --git a/gnu/packages/patches/icecat-CVE-2015-0797.patch b/gnu/packages/patches/icecat-CVE-2015-0797.patch
new file mode 100644
index 0000000000..5727ed753c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-0797.patch
@@ -0,0 +1,35 @@
+From 147543038273042f71284fa8487c71670163da5f Mon Sep 17 00:00:00 2001
+From: Ralph Giles <giles@mozilla.com>
+Date: Tue, 31 Mar 2015 16:18:22 -0700
+Subject: [PATCH] Bug 1080995 - Don't use the h264parser gstreamer element.
+ r=kinetik, a=sledru
+
+---
+ content/media/gstreamer/GStreamerFormatHelper.cpp | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/content/media/gstreamer/GStreamerFormatHelper.cpp b/content/media/gstreamer/GStreamerFormatHelper.cpp
+index 25095e7..ebd12c2 100644
+--- a/content/media/gstreamer/GStreamerFormatHelper.cpp
++++ b/content/media/gstreamer/GStreamerFormatHelper.cpp
+@@ -67,6 +67,7 @@ static char const * const sDefaultCodecCaps[][2] = {
+
+ static char const * const sPluginBlacklist[] = {
+ "flump3dec",
++ "h264parse",
+ };
+
+ GStreamerFormatHelper::GStreamerFormatHelper()
+@@ -251,7 +252,8 @@ static gboolean FactoryFilter(GstPluginFeature *aFeature, gpointer)
+ const gchar *className =
+ gst_element_factory_get_klass(GST_ELEMENT_FACTORY_CAST(aFeature));
+
+- if (!strstr(className, "Decoder") && !strstr(className, "Demux")) {
++ if (!strstr(className, "Decoder") && !strstr(className, "Demux") &&
++ !strstr(className, "Parser")) {
+ return FALSE;
+ }
+
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2708-pt1.patch b/gnu/packages/patches/icecat-CVE-2015-2708-pt1.patch
new file mode 100644
index 0000000000..e755d7531a
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2708-pt1.patch
@@ -0,0 +1,240 @@
+From 5f61ae17ec82d288a3fe4892ec999c0e20c486c0 Mon Sep 17 00:00:00 2001
+From: "Byron Campen [:bwc]" <docfaraday@gmail.com>
+Date: Mon, 6 Apr 2015 11:52:28 -0700
+Subject: [PATCH] Bug 1151139 - Simplify how we choose which streams to gather
+ stats from. r=mt, a=abillings
+
+---
+ ...t_peerConnection_offerRequiresReceiveAudio.html | 2 +
+ ...t_peerConnection_offerRequiresReceiveVideo.html | 2 +
+ ...rConnection_offerRequiresReceiveVideoAudio.html | 2 +
+ media/mtransport/nricectx.h | 13 +++++
+ media/mtransport/nricemediastream.cpp | 1 +
+ media/mtransport/nricemediastream.h | 5 +-
+ .../src/peerconnection/PeerConnectionImpl.cpp | 66 ++++++++++------------
+ .../src/peerconnection/PeerConnectionImpl.h | 2 +-
+ 8 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html
+index 69d7e49..d68c078 100644
+--- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html
++++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html
+@@ -17,6 +17,8 @@
+
+ runTest(function() {
+ var test = new PeerConnectionTest();
++ test.chain.remove('PC_LOCAL_CHECK_STATS');
++ test.chain.remove('PC_REMOTE_CHECK_STATS');
+ test.setOfferConstraints({ mandatory: { OfferToReceiveAudio: true } });
+ test.run();
+ });
+diff --git a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html
+index 5f1d0e5..0ecb0b7 100644
+--- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html
++++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html
+@@ -17,6 +17,8 @@
+
+ runTest(function() {
+ var test = new PeerConnectionTest();
++ test.chain.remove('PC_LOCAL_CHECK_STATS');
++ test.chain.remove('PC_REMOTE_CHECK_STATS');
+ test.setOfferConstraints({ mandatory: { OfferToReceiveVideo: true } });
+ test.run();
+ });
+diff --git a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html
+index c3dea10..78eb0d4 100644
+--- a/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html
++++ b/dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html
+@@ -17,6 +17,8 @@
+
+ runTest(function() {
+ var test = new PeerConnectionTest();
++ test.chain.remove('PC_LOCAL_CHECK_STATS');
++ test.chain.remove('PC_REMOTE_CHECK_STATS');
+ test.setOfferConstraints({ mandatory: {
+ OfferToReceiveVideo: true,
+ OfferToReceiveAudio: true
+diff --git a/media/mtransport/nricectx.h b/media/mtransport/nricectx.h
+index d1209a7..7350666 100644
+--- a/media/mtransport/nricectx.h
++++ b/media/mtransport/nricectx.h
+@@ -196,6 +196,19 @@ class NrIceCtx {
+ RefPtr<NrIceMediaStream> CreateStream(const std::string& name,
+ int components);
+
++ RefPtr<NrIceMediaStream> GetStream(size_t index) {
++ if (index < streams_.size()) {
++ return streams_[index];
++ }
++ return nullptr;
++ }
++
++ // Some might be null
++ size_t GetStreamCount() const
++ {
++ return streams_.size();
++ }
++
+ // The name of the ctx
+ const std::string& name() const { return name_; }
+
+diff --git a/media/mtransport/nricemediastream.cpp b/media/mtransport/nricemediastream.cpp
+index 9e96cb5..d2b6429 100644
+--- a/media/mtransport/nricemediastream.cpp
++++ b/media/mtransport/nricemediastream.cpp
+@@ -209,6 +209,7 @@ nsresult NrIceMediaStream::ParseAttributes(std::vector<std::string>&
+ return NS_ERROR_FAILURE;
+ }
+
++ has_parsed_attrs_ = true;
+ return NS_OK;
+ }
+
+diff --git a/media/mtransport/nricemediastream.h b/media/mtransport/nricemediastream.h
+index aba5fc3..2494ecf 100644
+--- a/media/mtransport/nricemediastream.h
++++ b/media/mtransport/nricemediastream.h
+@@ -149,6 +149,7 @@ class NrIceMediaStream {
+
+ // Parse remote attributes
+ nsresult ParseAttributes(std::vector<std::string>& candidates);
++ bool HasParsedAttributes() const { return has_parsed_attrs_; }
+
+ // Parse trickle ICE candidate
+ nsresult ParseTrickleCandidate(const std::string& candidate);
+@@ -204,7 +205,8 @@ class NrIceMediaStream {
+ name_(name),
+ components_(components),
+ stream_(nullptr),
+- opaque_(nullptr) {}
++ opaque_(nullptr),
++ has_parsed_attrs_(false) {}
+
+ DISALLOW_COPY_ASSIGN(NrIceMediaStream);
+
+@@ -214,6 +216,7 @@ class NrIceMediaStream {
+ const int components_;
+ nr_ice_media_stream *stream_;
+ ScopedDeletePtr<NrIceOpaque> opaque_;
++ bool has_parsed_attrs_;
+ };
+
+
+diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+index ebcc17d..c70e3e4 100644
+--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
++++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+@@ -149,7 +149,8 @@ PRLogModuleInfo *signalingLogInfo() {
+ namespace sipcc {
+
+ #ifdef MOZILLA_INTERNAL_API
+-RTCStatsQuery::RTCStatsQuery(bool internal) : internalStats(internal) {
++RTCStatsQuery::RTCStatsQuery(bool internal) : internalStats(internal),
++ grabAllLevels(false) {
+ }
+
+ RTCStatsQuery::~RTCStatsQuery() {
+@@ -2037,32 +2038,8 @@ PeerConnectionImpl::BuildStatsQuery_m(
+
+ query->iceCtx = mMedia->ice_ctx();
+
+- // From the list of MediaPipelines, determine the set of NrIceMediaStreams
+- // we are interested in.
+- std::set<size_t> levelsToGrab;
+- if (trackId) {
+- for (size_t p = 0; p < query->pipelines.Length(); ++p) {
+- size_t level = query->pipelines[p]->level();
+- MOZ_ASSERT(level);
+- levelsToGrab.insert(level);
+- }
+- } else {
+- // We want to grab all streams, so ignore the pipelines (this also ends up
+- // grabbing DataChannel streams, which is what we want)
+- for (size_t s = 0; s < mMedia->num_ice_media_streams(); ++s) {
+- levelsToGrab.insert(s + 1); // mIceStreams is 0-indexed
+- }
+- }
+-
+- for (auto s = levelsToGrab.begin(); s != levelsToGrab.end(); ++s) {
+- // TODO(bcampen@mozilla.com): I may need to revisit this for bundle.
+- // (Bug 786234)
+- RefPtr<NrIceMediaStream> temp(mMedia->ice_media_stream(*s - 1));
+- RefPtr<TransportFlow> flow(mMedia->GetTransportFlow(*s, false));
+- // flow can be null for unused levels, such as unused DataChannels
+- if (temp && flow) {
+- query->streams.AppendElement(temp);
+- }
++ if (!trackId) {
++ query->grabAllLevels = true;
+ }
+
+ return rv;
+@@ -2103,6 +2080,9 @@ static void RecordIceStats_s(
+ bool internalStats,
+ DOMHighResTimeStamp now,
+ RTCStatsReportInternal* report) {
++ if (!mediaStream.HasParsedAttributes()) {
++ return;
++ }
+
+ NS_ConvertASCIItoUTF16 componentId(mediaStream.name().c_str());
+ if (internalStats) {
+@@ -2292,20 +2272,32 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) {
+ break;
+ }
+ }
++
++ if (!query->grabAllLevels) {
++ // If we're grabbing all levels, that means we want datachannels too,
++ // which don't have pipelines.
++ if (query->iceCtx->GetStream(p - 1)) {
++ RecordIceStats_s(*query->iceCtx->GetStream(p - 1),
++ query->internalStats,
++ query->now,
++ &(query->report));
++ }
++ }
+ }
+
+- // Gather stats from ICE
+- for (size_t s = 0; s != query->streams.Length(); ++s) {
+- RecordIceStats_s(*query->streams[s],
+- query->internalStats,
+- query->now,
+- &(query->report));
++ if (query->grabAllLevels) {
++ for (size_t i = 0; i < query->iceCtx->GetStreamCount(); ++i) {
++ if (query->iceCtx->GetStream(i)) {
++ RecordIceStats_s(*query->iceCtx->GetStream(i),
++ query->internalStats,
++ query->now,
++ &(query->report));
++ }
++ }
+ }
+
+- // NrIceCtx and NrIceMediaStream must be destroyed on STS, so it is not safe
+- // to dispatch them back to main.
+- // We clear streams first to maintain destruction order
+- query->streams.Clear();
++ // NrIceCtx must be destroyed on STS, so it is not safe
++ // to dispatch it back to main.
+ query->iceCtx = nullptr;
+ return NS_OK;
+ }
+diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+index 847085c..497230a 100644
+--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
++++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+@@ -174,7 +174,7 @@ class RTCStatsQuery {
+ bool internalStats;
+ nsTArray<mozilla::RefPtr<mozilla::MediaPipeline>> pipelines;
+ mozilla::RefPtr<NrIceCtx> iceCtx;
+- nsTArray<mozilla::RefPtr<NrIceMediaStream>> streams;
++ bool grabAllLevels;
+ DOMHighResTimeStamp now;
+ };
+ #endif // MOZILLA_INTERNAL_API
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2708-pt2.patch b/gnu/packages/patches/icecat-CVE-2015-2708-pt2.patch
new file mode 100644
index 0000000000..9788806557
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2708-pt2.patch
@@ -0,0 +1,284 @@
+From 272c1ba11fac7a9ceede2f4f737bb27b4bbcad71 Mon Sep 17 00:00:00 2001
+From: Steve Fink <sfink@mozilla.com>
+Date: Thu, 19 Mar 2015 20:50:57 -0700
+Subject: [PATCH] Bug 1120655 - Suppress zone/compartment collection while
+ iterating. r=terrence, a=bkerensa
+
+---
+ js/src/gc/Zone.h | 9 ++++----
+ js/src/jsgc.cpp | 57 +++++++++++++++++++++++++++++++++++----------------
+ js/src/jsgc.h | 11 +++++++++-
+ js/src/vm/Runtime.cpp | 1 +
+ js/src/vm/Runtime.h | 3 +++
+ 5 files changed, 58 insertions(+), 23 deletions(-)
+
+diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
+index e7f687a..dd058f0 100644
+--- a/js/src/gc/Zone.h
++++ b/js/src/gc/Zone.h
+@@ -353,10 +353,11 @@ enum ZoneSelector {
+
+ class ZonesIter {
+ private:
++ gc::AutoEnterIteration iterMarker;
+ JS::Zone **it, **end;
+
+ public:
+- ZonesIter(JSRuntime *rt, ZoneSelector selector) {
++ ZonesIter(JSRuntime *rt, ZoneSelector selector) : iterMarker(rt) {
+ it = rt->zones.begin();
+ end = rt->zones.end();
+
+@@ -427,13 +428,13 @@ struct CompartmentsInZoneIter
+ template<class ZonesIterT>
+ class CompartmentsIterT
+ {
+- private:
++ gc::AutoEnterIteration iterMarker;
+ ZonesIterT zone;
+ mozilla::Maybe<CompartmentsInZoneIter> comp;
+
+ public:
+ explicit CompartmentsIterT(JSRuntime *rt)
+- : zone(rt)
++ : iterMarker(rt), zone(rt)
+ {
+ if (zone.done())
+ comp.construct();
+@@ -442,7 +443,7 @@ class CompartmentsIterT
+ }
+
+ CompartmentsIterT(JSRuntime *rt, ZoneSelector selector)
+- : zone(rt, selector)
++ : iterMarker(rt), zone(rt, selector)
+ {
+ if (zone.done())
+ comp.construct();
+diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
+index 15c86c8..1dfe0ab 100644
+--- a/js/src/jsgc.cpp
++++ b/js/src/jsgc.cpp
+@@ -2525,7 +2525,7 @@ ReleaseObservedTypes(JSRuntime* rt)
+ * arbitrary compartment in the zone.
+ */
+ static void
+-SweepCompartments(FreeOp *fop, Zone *zone, bool keepAtleastOne, bool lastGC)
++SweepCompartments(FreeOp *fop, Zone *zone, bool keepAtleastOne, bool destroyingRuntime)
+ {
+ JSRuntime *rt = zone->runtimeFromMainThread();
+ JSDestroyCompartmentCallback callback = rt->destroyCompartmentCallback;
+@@ -2543,7 +2543,7 @@ SweepCompartments(FreeOp *fop, Zone *zone, bool keepAtleastOne, bool lastGC)
+ * deleted and keepAtleastOne is true.
+ */
+ bool dontDelete = read == end && !foundOne && keepAtleastOne;
+- if ((!comp->marked && !dontDelete) || lastGC) {
++ if ((!comp->marked && !dontDelete) || destroyingRuntime) {
+ if (callback)
+ callback(fop, comp);
+ if (comp->principals)
+@@ -2559,9 +2559,13 @@ SweepCompartments(FreeOp *fop, Zone *zone, bool keepAtleastOne, bool lastGC)
+ }
+
+ static void
+-SweepZones(FreeOp *fop, bool lastGC)
++SweepZones(FreeOp *fop, bool destroyingRuntime)
+ {
+ JSRuntime *rt = fop->runtime();
++ MOZ_ASSERT_IF(destroyingRuntime, rt->numActiveZoneIters == 0);
++ if (rt->numActiveZoneIters)
++ return;
++
+ JSZoneCallback callback = rt->destroyZoneCallback;
+
+ /* Skip the atomsCompartment zone. */
+@@ -2576,17 +2580,17 @@ SweepZones(FreeOp* fop, bool lastGC)
+
+ if (zone->wasGCStarted()) {
+ if ((zone->allocator.arenas.arenaListsAreEmpty() && !zone->hasMarkedCompartments()) ||
+- lastGC)
++ destroyingRuntime)
+ {
+ zone->allocator.arenas.checkEmptyFreeLists();
+ if (callback)
+ callback(zone);
+- SweepCompartments(fop, zone, false, lastGC);
++ SweepCompartments(fop, zone, false, destroyingRuntime);
+ JS_ASSERT(zone->compartments.empty());
+ fop->delete_(zone);
+ continue;
+ }
+- SweepCompartments(fop, zone, true, lastGC);
++ SweepCompartments(fop, zone, true, destroyingRuntime);
+ }
+ *write++ = zone;
+ }
+@@ -3787,7 +3791,7 @@ EndSweepingZoneGroup(JSRuntime *rt)
+ }
+
+ static void
+-BeginSweepPhase(JSRuntime *rt, bool lastGC)
++BeginSweepPhase(JSRuntime *rt, bool destroyingRuntime)
+ {
+ /*
+ * Sweep phase.
+@@ -3804,7 +3808,7 @@ BeginSweepPhase(JSRuntime *rt, bool lastGC)
+ gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
+
+ #ifdef JS_THREADSAFE
+- rt->gcSweepOnBackgroundThread = !lastGC && rt->useHelperThreads();
++ rt->gcSweepOnBackgroundThread = !destroyingRuntime && rt->useHelperThreads();
+ #endif
+
+ #ifdef DEBUG
+@@ -3903,12 +3907,12 @@ SweepPhase(JSRuntime *rt, SliceBudget &sliceBudget)
+ }
+
+ static void
+-EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC)
++EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool destroyingRuntime)
+ {
+ gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
+ FreeOp fop(rt, rt->gcSweepOnBackgroundThread);
+
+- JS_ASSERT_IF(lastGC, !rt->gcSweepOnBackgroundThread);
++ JS_ASSERT_IF(destroyingRuntime, !rt->gcSweepOnBackgroundThread);
+
+ JS_ASSERT(rt->gcMarker.isDrained());
+ rt->gcMarker.stop();
+@@ -3959,8 +3963,8 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC)
+ * This removes compartments from rt->compartment, so we do it last to make
+ * sure we don't miss sweeping any compartments.
+ */
+- if (!lastGC)
+- SweepZones(&fop, lastGC);
++ if (!destroyingRuntime)
++ SweepZones(&fop, destroyingRuntime);
+
+ if (!rt->gcSweepOnBackgroundThread) {
+ /*
+@@ -4001,8 +4005,8 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC)
+ rt->freeLifoAlloc.freeAll();
+
+ /* Ensure the compartments get swept if it's the last GC. */
+- if (lastGC)
+- SweepZones(&fop, lastGC);
++ if (destroyingRuntime)
++ SweepZones(&fop, destroyingRuntime);
+ }
+
+ for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
+@@ -4339,7 +4343,7 @@ IncrementalCollectSlice(JSRuntime *rt,
+ AutoCopyFreeListToArenasForGC copy(rt);
+ AutoGCSlice slice(rt);
+
+- bool lastGC = (reason == JS::gcreason::DESTROY_RUNTIME);
++ bool destroyingRuntime = (reason == JS::gcreason::DESTROY_RUNTIME);
+
+ gc::State initialState = rt->gcIncrementalState;
+
+@@ -4384,7 +4388,7 @@ IncrementalCollectSlice(JSRuntime *rt,
+ return;
+ }
+
+- if (!lastGC)
++ if (!destroyingRuntime)
+ PushZealSelectedObjects(rt);
+
+ rt->gcIncrementalState = MARK;
+@@ -4426,7 +4430,7 @@ IncrementalCollectSlice(JSRuntime *rt,
+ * This runs to completion, but we don't continue if the budget is
+ * now exhasted.
+ */
+- BeginSweepPhase(rt, lastGC);
++ BeginSweepPhase(rt, destroyingRuntime);
+ if (sliceBudget.isOverBudget())
+ break;
+
+@@ -4445,7 +4449,7 @@ IncrementalCollectSlice(JSRuntime *rt,
+ if (!finished)
+ break;
+
+- EndSweepPhase(rt, gckind, lastGC);
++ EndSweepPhase(rt, gckind, destroyingRuntime);
+
+ if (rt->gcSweepOnBackgroundThread)
+ rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
+@@ -5386,3 +5390,20 @@ JS::AutoAssertNoGC::~AutoAssertNoGC()
+ MOZ_ASSERT(gcNumber == runtime->gcNumber, "GC ran inside an AutoAssertNoGC scope.");
+ }
+ #endif
++
++namespace js {
++namespace gc {
++
++AutoEnterIteration::AutoEnterIteration(JSRuntime *rt_) : rt(rt_)
++{
++ ++rt->numActiveZoneIters;
++}
++
++AutoEnterIteration::~AutoEnterIteration()
++{
++ MOZ_ASSERT(rt->numActiveZoneIters);
++ --rt->numActiveZoneIters;
++}
++
++} /* namespace gc */
++} /* namespace js */
+diff --git a/js/src/jsgc.h b/js/src/jsgc.h
+index 825cff5..ca331c0 100644
+--- a/js/src/jsgc.h
++++ b/js/src/jsgc.h
+@@ -1077,7 +1077,7 @@ MaybeVerifyBarriers(JSContext* cx, bool always = false)
+ /*
+ * Instances of this class set the |JSRuntime::suppressGC| flag for the duration
+ * that they are live. Use of this class is highly discouraged. Please carefully
+- * read the comment in jscntxt.h above |suppressGC| and take all appropriate
++ * read the comment in vm/Runtime.h above |suppressGC| and take all appropriate
+ * precautions before instantiating this class.
+ */
+ class AutoSuppressGC
+@@ -1113,6 +1113,15 @@ class AutoEnterOOMUnsafeRegion
+ class AutoEnterOOMUnsafeRegion {};
+ #endif /* DEBUG */
+
++/* Prevent compartments and zones from being collected during iteration. */
++class AutoEnterIteration {
++ JSRuntime *rt;
++
++ public:
++ AutoEnterIteration(JSRuntime *rt_);
++ ~AutoEnterIteration();
++};
++
+ } /* namespace gc */
+
+ #ifdef DEBUG
+diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
+index bb5c8680..0d8c6cd 100644
+--- a/js/src/vm/Runtime.cpp
++++ b/js/src/vm/Runtime.cpp
+@@ -195,6 +195,7 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime, JSUseHelperThreads useHelperThrea
+ gcShouldCleanUpEverything(false),
+ gcGrayBitsValid(false),
+ gcIsNeeded(0),
++ numActiveZoneIters(0),
+ gcStats(thisFromCtor()),
+ gcNumber(0),
+ gcStartNumber(0),
+diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
+index 5aeb924..ba4180e 100644
+--- a/js/src/vm/Runtime.h
++++ b/js/src/vm/Runtime.h
+@@ -1061,6 +1061,9 @@ struct JSRuntime : public JS::shadow::Runtime,
+ */
+ volatile uintptr_t gcIsNeeded;
+
++ mozilla::Atomic<size_t, mozilla::ReleaseAcquire> numActiveZoneIters;
++ friend class js::gc::AutoEnterIteration;
++
+ js::gcstats::Statistics gcStats;
+
+ /* Incremented on every GC slice. */
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2708-pt3.patch b/gnu/packages/patches/icecat-CVE-2015-2708-pt3.patch
new file mode 100644
index 0000000000..f684804d0b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2708-pt3.patch
@@ -0,0 +1,228 @@
+From 4dcbca8b3c26b451e1376cd1b7c88ab984a45b39 Mon Sep 17 00:00:00 2001
+From: Mats Palmgren <mats@mozilla.com>
+Date: Tue, 14 Apr 2015 22:12:39 -0400
+Subject: [PATCH] Bug 1143299 - Make frame insertion methods deal with
+ aPrevFrame being on an overflow list. r=roc, a=bkerensa
+
+---
+ layout/generic/nsBlockFrame.cpp | 18 ++++++++++++---
+ layout/generic/nsBlockFrame.h | 14 ++++++++----
+ layout/generic/nsContainerFrame.cpp | 41 +++++++++++++++++++---------------
+ layout/tables/nsTableFrame.cpp | 2 ++
+ layout/tables/nsTableRowFrame.cpp | 2 ++
+ layout/tables/nsTableRowGroupFrame.cpp | 2 ++
+ 6 files changed, 54 insertions(+), 25 deletions(-)
+
+diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp
+index a011bcf..70d5297 100644
+--- a/layout/generic/nsBlockFrame.cpp
++++ b/layout/generic/nsBlockFrame.cpp
+@@ -1049,7 +1049,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
+ state.mOverflowTracker = &tracker;
+
+ // Drain & handle pushed floats
+- DrainPushedFloats(state);
++ DrainPushedFloats();
+ nsOverflowAreas fcBounds;
+ nsReflowStatus fcStatus = NS_FRAME_COMPLETE;
+ ReflowPushedFloats(state, fcBounds, fcStatus);
+@@ -4438,9 +4438,13 @@ nsBlockFrame::DrainSelfOverflowList()
+ * might push some of them on). Floats with placeholders in this block
+ * are reflowed by (nsBlockReflowState/nsLineLayout)::AddFloat, which
+ * also maintains these invariants.
++ *
++ * DrainSelfPushedFloats moves any pushed floats from this block's own
++ * PushedFloats list back into mFloats. DrainPushedFloats additionally
++ * moves frames from its prev-in-flow's PushedFloats list into mFloats.
+ */
+ void
+-nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState)
++nsBlockFrame::DrainSelfPushedFloats()
+ {
+ #ifdef DEBUG
+ // Between when we drain pushed floats and when we complete reflow,
+@@ -4503,12 +4507,18 @@ nsBlockFrame::DrainPushedFloats(nsBlockReflowState& aState)
+ RemovePushedFloats()->Delete(presContext->PresShell());
+ }
+ }
++}
++
++void
++nsBlockFrame::DrainPushedFloats()
++{
++ DrainSelfPushedFloats();
+
+ // After our prev-in-flow has completed reflow, it may have a pushed
+ // floats list, containing floats that we need to own. Take these.
+ nsBlockFrame* prevBlock = static_cast<nsBlockFrame*>(GetPrevInFlow());
+ if (prevBlock) {
+- AutoFrameListPtr list(presContext, prevBlock->RemovePushedFloats());
++ AutoFrameListPtr list(PresContext(), prevBlock->RemovePushedFloats());
+ if (list && list->NotEmpty()) {
+ mFloats.InsertFrames(this, nullptr, *list);
+ }
+@@ -4711,6 +4721,7 @@ nsBlockFrame::AppendFrames(ChildListID aListID,
+ return nsContainerFrame::AppendFrames(aListID, aFrameList);
+ }
+ else if (kFloatList == aListID) {
++ DrainSelfPushedFloats(); // ensure the last frame is in mFloats
+ mFloats.AppendFrames(nullptr, aFrameList);
+ return NS_OK;
+ }
+@@ -4757,6 +4768,7 @@ nsBlockFrame::InsertFrames(ChildListID aListID,
+ return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
+ }
+ else if (kFloatList == aListID) {
++ DrainSelfPushedFloats(); // ensure aPrevFrame is in mFloats
+ mFloats.InsertFrames(this, aPrevFrame, aFrameList);
+ return NS_OK;
+ }
+diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h
+index 1a6bb1e..07f7508 100644
+--- a/layout/generic/nsBlockFrame.h
++++ b/layout/generic/nsBlockFrame.h
+@@ -533,10 +533,16 @@ protected:
+ return GetStateBits() & NS_BLOCK_HAS_OVERFLOW_OUT_OF_FLOWS;
+ }
+
+- /** grab pushed floats from this block's prevInFlow, and splice
+- * them into this block's mFloats list.
+- */
+- void DrainPushedFloats(nsBlockReflowState& aState);
++ /**
++ * Moves frames from our PushedFloats list back into our mFloats list.
++ */
++ void DrainSelfPushedFloats();
++
++ /**
++ * First calls DrainSelfPushedFloats() then grabs pushed floats from this
++ * block's prev-in-flow, and splice them into this block's mFloats list too.
++ */
++ void DrainPushedFloats();
+
+ /** Load all our floats into the float manager (without reflowing them).
+ * Assumes float manager is in our own coordinate system.
+diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
+index 76f0748..3ffcba7 100644
+--- a/layout/generic/nsContainerFrame.cpp
++++ b/layout/generic/nsContainerFrame.cpp
+@@ -102,16 +102,18 @@ nsContainerFrame::AppendFrames(ChildListID aListID,
+ return NS_ERROR_INVALID_ARG;
+ }
+ }
+- if (aFrameList.NotEmpty()) {
+- mFrames.AppendFrames(this, aFrameList);
+
+- // Ask the parent frame to reflow me.
+- if (aListID == kPrincipalList)
+- {
+- PresContext()->PresShell()->
+- FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+- NS_FRAME_HAS_DIRTY_CHILDREN);
+- }
++ if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
++ return NS_OK;
++ }
++
++ DrainSelfOverflowList(); // ensure the last frame is in mFrames
++ mFrames.AppendFrames(this, aFrameList);
++
++ if (aListID != kNoReflowPrincipalList) {
++ PresContext()->PresShell()->
++ FrameNeedsReflow(this, nsIPresShell::eTreeChange,
++ NS_FRAME_HAS_DIRTY_CHILDREN);
+ }
+ return NS_OK;
+ }
+@@ -131,16 +133,19 @@ nsContainerFrame::InsertFrames(ChildListID aListID,
+ return NS_ERROR_INVALID_ARG;
+ }
+ }
+- if (aFrameList.NotEmpty()) {
+- // Insert frames after aPrevFrame
+- mFrames.InsertFrames(this, aPrevFrame, aFrameList);
+
+- if (aListID == kPrincipalList)
+- {
+- PresContext()->PresShell()->
+- FrameNeedsReflow(this, nsIPresShell::eTreeChange,
+- NS_FRAME_HAS_DIRTY_CHILDREN);
+- }
++ if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
++ return NS_OK;
++ }
++
++ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
++ mFrames.InsertFrames(this, aPrevFrame, aFrameList);
++
++ if (aListID != kNoReflowPrincipalList) {
++ PresContext()->PresShell()->
++ FrameNeedsReflow(this, nsIPresShell::eTreeChange,
++ NS_FRAME_HAS_DIRTY_CHILDREN);
++
+ }
+ return NS_OK;
+ }
+diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
+index 60613ba..44088da 100644
+--- a/layout/tables/nsTableFrame.cpp
++++ b/layout/tables/nsTableFrame.cpp
+@@ -2232,6 +2232,7 @@ nsTableFrame::AppendFrames(ChildListID aListID,
+ InsertColGroups(startColIndex,
+ nsFrameList::Slice(mColGroups, f, f->GetNextSibling()));
+ } else if (IsRowGroup(display->mDisplay)) {
++ DrainSelfOverflowList(); // ensure the last frame is in mFrames
+ // Append the new row group frame to the sibling chain
+ mFrames.AppendFrame(nullptr, f);
+
+@@ -2404,6 +2405,7 @@ nsTableFrame::HomogenousInsertFrames(ChildListID aListID,
+ InsertColGroups(startColIndex, newColgroups);
+ } else if (IsRowGroup(display->mDisplay)) {
+ NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
++ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
+ // Insert the frames in the sibling chain
+ const nsFrameList::Slice& newRowGroups =
+ mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
+diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp
+index d1c493b..2351de3 100644
+--- a/layout/tables/nsTableRowFrame.cpp
++++ b/layout/tables/nsTableRowFrame.cpp
+@@ -182,6 +182,7 @@ nsTableRowFrame::AppendFrames(ChildListID aListID,
+ {
+ NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
+
++ DrainSelfOverflowList(); // ensure the last frame is in mFrames
+ const nsFrameList::Slice& newCells = mFrames.AppendFrames(nullptr, aFrameList);
+
+ // Add the new cell frames to the table
+@@ -208,6 +209,7 @@ nsTableRowFrame::InsertFrames(ChildListID aListID,
+ NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
+ NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
+ "inserting after sibling frame with different parent");
++ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
+ //Insert Frames in the frame list
+ const nsFrameList::Slice& newCells = mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
+
+diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp
+index 34aaf02..40b349b 100644
+--- a/layout/tables/nsTableRowGroupFrame.cpp
++++ b/layout/tables/nsTableRowGroupFrame.cpp
+@@ -1389,6 +1389,7 @@ nsTableRowGroupFrame::AppendFrames(ChildListID aListID,
+ {
+ NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
+
++ DrainSelfOverflowList(); // ensure the last frame is in mFrames
+ ClearRowCursor();
+
+ // collect the new row frames in an array
+@@ -1430,6 +1431,7 @@ nsTableRowGroupFrame::InsertFrames(ChildListID aListID,
+ NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
+ "inserting after sibling frame with different parent");
+
++ DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
+ ClearRowCursor();
+
+ // collect the new row frames in an array
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2708-pt4.patch b/gnu/packages/patches/icecat-CVE-2015-2708-pt4.patch
new file mode 100644
index 0000000000..eb2295f5ac
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2708-pt4.patch
@@ -0,0 +1,26 @@
+From e6082e031f0fa2a4a7a63ff124c6f22aeb75393d Mon Sep 17 00:00:00 2001
+From: Terrence Cole <terrence@mozilla.com>
+Date: Fri, 10 Apr 2015 08:58:26 -0700
+Subject: [PATCH] Bug 1152177 - Make jsid and Value pre barriers symetrical.
+ r=jonco, a=abillings
+
+---
+ js/src/gc/Barrier.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h
+index 7efd785..9fc6bd0 100644
+--- a/js/src/gc/Barrier.h
++++ b/js/src/gc/Barrier.h
+@@ -1062,6 +1062,8 @@ class BarrieredId
+ JS_ASSERT(obj == JSID_TO_OBJECT(value));
+ }
+ } else if (JSID_IS_STRING(value)) {
++ if (StringIsPermanentAtom(JSID_TO_STRING(value)))
++ return;
+ JSString *str = JSID_TO_STRING(value);
+ JS::shadow::Zone *shadowZone = ShadowZoneOfStringFromAnyThread(str);
+ if (shadowZone->needsBarrier()) {
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2710-pt1.patch b/gnu/packages/patches/icecat-CVE-2015-2710-pt1.patch
new file mode 100644
index 0000000000..4f119f6fe9
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2710-pt1.patch
@@ -0,0 +1,199 @@
+From 0bd8486f4088c0845514986f61861688e0be011d Mon Sep 17 00:00:00 2001
+From: Cameron McCormack <cam@mcc.id.au>
+Date: Mon, 6 Apr 2015 09:11:55 -0400
+Subject: [PATCH] Bug 1149542 - Part 1: Return early from SVG text layout if we
+ discover mPositions is not long enough. r=dholbert, a=sledru
+
+---
+ layout/svg/SVGTextFrame.cpp | 59 +++++++++++++++++++++++++++++++--------------
+ layout/svg/SVGTextFrame.h | 23 ++++++++++++------
+ 2 files changed, 56 insertions(+), 26 deletions(-)
+
+diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp
+index 721e699..45327881 100644
+--- a/layout/svg/SVGTextFrame.cpp
++++ b/layout/svg/SVGTextFrame.cpp
+@@ -14,6 +14,7 @@
+ #include "gfxTypes.h"
+ #include "LookAndFeel.h"
+ #include "mozilla/gfx/2D.h"
++#include "mozilla/Likely.h"
+ #include "nsAlgorithm.h"
+ #include "nsBlockFrame.h"
+ #include "nsCaret.h"
+@@ -4316,23 +4317,28 @@ ShouldStartRunAtIndex(const nsTArray<CharPosition>& aPositions,
+ return false;
+ }
+
+-uint32_t
+-SVGTextFrame::ResolvePositions(nsIContent* aContent,
+- uint32_t aIndex,
+- bool aInTextPath,
+- bool& aForceStartOfChunk,
+- nsTArray<gfxPoint>& aDeltas)
++bool
++SVGTextFrame::ResolvePositionsForNode(nsIContent* aContent,
++ uint32_t& aIndex,
++ bool aInTextPath,
++ bool& aForceStartOfChunk,
++ nsTArray<gfxPoint>& aDeltas)
+ {
+ if (aContent->IsNodeOfType(nsINode::eTEXT)) {
+ // We found a text node.
+ uint32_t length = static_cast<nsTextNode*>(aContent)->TextLength();
+ if (length) {
++ uint32_t end = aIndex + length;
++ if (MOZ_UNLIKELY(end > mPositions.Length())) {
++ MOZ_ASSERT_UNREACHABLE("length of mPositions does not match characters "
++ "found by iterating content");
++ return false;
++ }
+ if (aForceStartOfChunk) {
+ // Note this character as starting a new anchored chunk.
+ mPositions[aIndex].mStartOfChunk = true;
+ aForceStartOfChunk = false;
+ }
+- uint32_t end = aIndex + length;
+ while (aIndex < end) {
+ // Record whether each of these characters should start a new rendered
+ // run. That is always the case for characters on a text path.
+@@ -4345,18 +4351,23 @@ SVGTextFrame::ResolvePositions(nsIContent* aContent,
+ aIndex++;
+ }
+ }
+- return aIndex;
++ return true;
+ }
+
+ // Skip past elements that aren't text content elements.
+ if (!IsTextContentElement(aContent)) {
+- return aIndex;
++ return true;
+ }
+
+ if (aContent->Tag() == nsGkAtoms::textPath) {
+ // <textPath> elements are as if they are specified with x="0" y="0", but
+ // only if they actually have some text content.
+ if (HasTextContent(aContent)) {
++ if (MOZ_UNLIKELY(aIndex >= mPositions.Length())) {
++ MOZ_ASSERT_UNREACHABLE("length of mPositions does not match characters "
++ "found by iterating content");
++ return false;
++ }
+ mPositions[aIndex].mPosition = gfxPoint();
+ mPositions[aIndex].mStartOfChunk = true;
+ }
+@@ -4376,8 +4387,14 @@ SVGTextFrame::ResolvePositions(nsIContent* aContent,
+ rotate = &animatedRotate->GetAnimValue();
+ }
+
+- uint32_t count = GetTextContentLength(aContent);
+ bool percentages = false;
++ uint32_t count = GetTextContentLength(aContent);
++
++ if (MOZ_UNLIKELY(aIndex + count > mPositions.Length())) {
++ MOZ_ASSERT_UNREACHABLE("length of mPositions does not match characters "
++ "found by iterating content");
++ return false;
++ }
+
+ // New text anchoring chunks start at each character assigned a position
+ // with x="" or y="", or if we forced one with aForceStartOfChunk due to
+@@ -4456,8 +4473,11 @@ SVGTextFrame::ResolvePositions(nsIContent* aContent,
+ for (nsIContent* child = aContent->GetFirstChild();
+ child;
+ child = child->GetNextSibling()) {
+- aIndex = ResolvePositions(child, aIndex, inTextPath, aForceStartOfChunk,
+- aDeltas);
++ bool ok = ResolvePositionsForNode(child, aIndex, inTextPath,
++ aForceStartOfChunk, aDeltas);
++ if (!ok) {
++ return false;
++ }
+ }
+
+ if (aContent->Tag() == nsGkAtoms::textPath) {
+@@ -4465,7 +4485,7 @@ SVGTextFrame::ResolvePositions(nsIContent* aContent,
+ aForceStartOfChunk = true;
+ }
+
+- return aIndex;
++ return true;
+ }
+
+ bool
+@@ -4501,8 +4521,10 @@ SVGTextFrame::ResolvePositions(nsTArray<gfxPoint>& aDeltas,
+
+ // Recurse over the content and fill in character positions as we go.
+ bool forceStartOfChunk = false;
+- return ResolvePositions(mContent, 0, aRunPerGlyph,
+- forceStartOfChunk, aDeltas) != 0;
++ index = 0;
++ bool ok = ResolvePositionsForNode(mContent, index, aRunPerGlyph,
++ forceStartOfChunk, aDeltas);
++ return ok && index > 0;
+ }
+
+ void
+@@ -4958,9 +4980,10 @@ SVGTextFrame::DoGlyphPositioning()
+ // Get the x, y, dx, dy, rotate values for the subtree.
+ nsTArray<gfxPoint> deltas;
+ if (!ResolvePositions(deltas, adjustingTextLength)) {
+- // If ResolvePositions returned false, it means that there were some
+- // characters in the DOM but none of them are displayed. Clear out
+- // mPositions so that we don't attempt to do any painting later.
++ // If ResolvePositions returned false, it means either there were some
++ // characters in the DOM but none of them are displayed, or there was
++ // an error in processing mPositions. Clear out mPositions so that we don't
++ // attempt to do any painting later.
+ mPositions.Clear();
+ return;
+ }
+diff --git a/layout/svg/SVGTextFrame.h b/layout/svg/SVGTextFrame.h
+index 48951f7..912af8b 100644
+--- a/layout/svg/SVGTextFrame.h
++++ b/layout/svg/SVGTextFrame.h
+@@ -505,15 +505,18 @@ private:
+ * Recursive helper for ResolvePositions below.
+ *
+ * @param aContent The current node.
+- * @param aIndex The current character index.
++ * @param aIndex (in/out) The current character index.
+ * @param aInTextPath Whether we are currently under a <textPath> element.
+- * @param aForceStartOfChunk Whether the next character we find should start a
+- * new anchored chunk.
+- * @return The character index we got up to.
++ * @param aForceStartOfChunk (in/out) Whether the next character we find
++ * should start a new anchored chunk.
++ * @param aDeltas (in/out) Receives the resolved dx/dy values for each
++ * character.
++ * @return false if we discover that mPositions did not have enough
++ * elements; true otherwise.
+ */
+- uint32_t ResolvePositions(nsIContent* aContent, uint32_t aIndex,
+- bool aInTextPath, bool& aForceStartOfChunk,
+- nsTArray<gfxPoint>& aDeltas);
++ bool ResolvePositionsForNode(nsIContent* aContent, uint32_t& aIndex,
++ bool aInTextPath, bool& aForceStartOfChunk,
++ nsTArray<gfxPoint>& aDeltas);
+
+ /**
+ * Initializes mPositions with character position information based on
+@@ -521,9 +524,13 @@ private:
+ * was not given for that character. Also fills aDeltas with values based on
+ * dx/dy attributes.
+ *
++ * @param aDeltas (in/out) Receives the resolved dx/dy values for each
++ * character.
+ * @param aRunPerGlyph Whether mPositions should record that a new run begins
+ * at each glyph.
+- * @return True if we recorded any positions.
++ * @return false if we did not record any positions (due to having no
++ * displayed characters) or if we discover that mPositions did not have
++ * enough elements; true otherwise.
+ */
+ bool ResolvePositions(nsTArray<gfxPoint>& aDeltas, bool aRunPerGlyph);
+
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2710-pt2.patch b/gnu/packages/patches/icecat-CVE-2015-2710-pt2.patch
new file mode 100644
index 0000000000..26a10ca2e4
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2710-pt2.patch
@@ -0,0 +1,64 @@
+From f7c0070831e72735c43beb426ac0c2ce33403f4f Mon Sep 17 00:00:00 2001
+From: Cameron McCormack <cam@mcc.id.au>
+Date: Mon, 6 Apr 2015 09:12:06 -0400
+Subject: [PATCH] Bug 1149542 - Part 2: Track undisplayed characters before
+ empty text frames properly. r=dholbert, a=sledru
+
+---
+ layout/svg/SVGTextFrame.cpp | 29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp
+index 45327881..9d331b8 100644
+--- a/layout/svg/SVGTextFrame.cpp
++++ b/layout/svg/SVGTextFrame.cpp
+@@ -290,22 +290,25 @@ GetNonEmptyTextFrameAndNode(nsIFrame* aFrame,
+ nsTextNode*& aTextNode)
+ {
+ nsTextFrame* text = do_QueryFrame(aFrame);
+- if (!text) {
+- return false;
+- }
++ bool isNonEmptyTextFrame = text && text->GetContentLength() != 0;
+
+- nsIContent* content = text->GetContent();
+- NS_ASSERTION(content && content->IsNodeOfType(nsINode::eTEXT),
+- "unexpected content type for nsTextFrame");
++ if (isNonEmptyTextFrame) {
++ nsIContent* content = text->GetContent();
++ NS_ASSERTION(content && content->IsNodeOfType(nsINode::eTEXT),
++ "unexpected content type for nsTextFrame");
+
+- nsTextNode* node = static_cast<nsTextNode*>(content);
+- if (node->TextLength() == 0) {
+- return false;
++ nsTextNode* node = static_cast<nsTextNode*>(content);
++ MOZ_ASSERT(node->TextLength() != 0,
++ "frame's GetContentLength() should be 0 if the text node "
++ "has no content");
++
++ aTextFrame = text;
++ aTextNode = node;
+ }
+
+- aTextFrame = text;
+- aTextNode = node;
+- return true;
++ MOZ_ASSERT(IsNonEmptyTextFrame(aFrame) == isNonEmptyTextFrame,
++ "our logic should agree with IsNonEmptyTextFrame");
++ return isNonEmptyTextFrame;
+ }
+
+ /**
+@@ -1298,7 +1301,7 @@ GetUndisplayedCharactersBeforeFrame(nsTextFrame* aFrame)
+ /**
+ * Traverses the nsTextFrames for an SVGTextFrame and records a
+ * TextNodeCorrespondenceProperty on each for the number of undisplayed DOM
+- * characters between each frame. This is done by iterating simultaenously
++ * characters between each frame. This is done by iterating simultaneously
+ * over the nsTextNodes and nsTextFrames and noting when nsTextNodes (or
+ * parts of them) are skipped when finding the next nsTextFrame.
+ */
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2710-pt3.patch b/gnu/packages/patches/icecat-CVE-2015-2710-pt3.patch
new file mode 100644
index 0000000000..6759506213
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2710-pt3.patch
@@ -0,0 +1,50 @@
+From 2cda46e6158a459b56b392c8e389b055fdf740ca Mon Sep 17 00:00:00 2001
+From: Ryan VanderMeulen <ryanvm@gmail.com>
+Date: Mon, 6 Apr 2015 22:59:41 -0400
+Subject: [PATCH] Bug 1149542 - Replace MOZ_ASSERT_UNREACHABLE with MOZ_ASSERT.
+ r=dholbert, a=bustage
+
+---
+ layout/svg/SVGTextFrame.cpp | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp
+index 9d331b8..e7b7275 100644
+--- a/layout/svg/SVGTextFrame.cpp
++++ b/layout/svg/SVGTextFrame.cpp
+@@ -4333,8 +4333,8 @@ SVGTextFrame::ResolvePositionsForNode(nsIContent* aContent,
+ if (length) {
+ uint32_t end = aIndex + length;
+ if (MOZ_UNLIKELY(end > mPositions.Length())) {
+- MOZ_ASSERT_UNREACHABLE("length of mPositions does not match characters "
+- "found by iterating content");
++ MOZ_ASSERT(false, "length of mPositions does not match characters "
++ "found by iterating content");
+ return false;
+ }
+ if (aForceStartOfChunk) {
+@@ -4367,8 +4367,8 @@ SVGTextFrame::ResolvePositionsForNode(nsIContent* aContent,
+ // only if they actually have some text content.
+ if (HasTextContent(aContent)) {
+ if (MOZ_UNLIKELY(aIndex >= mPositions.Length())) {
+- MOZ_ASSERT_UNREACHABLE("length of mPositions does not match characters "
+- "found by iterating content");
++ MOZ_ASSERT(false, "length of mPositions does not match characters "
++ "found by iterating content");
+ return false;
+ }
+ mPositions[aIndex].mPosition = gfxPoint();
+@@ -4394,8 +4394,8 @@ SVGTextFrame::ResolvePositionsForNode(nsIContent* aContent,
+ uint32_t count = GetTextContentLength(aContent);
+
+ if (MOZ_UNLIKELY(aIndex + count > mPositions.Length())) {
+- MOZ_ASSERT_UNREACHABLE("length of mPositions does not match characters "
+- "found by iterating content");
++ MOZ_ASSERT(false, "length of mPositions does not match characters "
++ "found by iterating content");
+ return false;
+ }
+
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2713-pt1.patch b/gnu/packages/patches/icecat-CVE-2015-2713-pt1.patch
new file mode 100644
index 0000000000..9e52759ae8
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2713-pt1.patch
@@ -0,0 +1,102 @@
+From 2b1c90da3e849e1c9d7457658290aa8eb01d0fa9 Mon Sep 17 00:00:00 2001
+From: Mats Palmgren <mats@mozilla.com>
+Date: Thu, 16 Apr 2015 09:04:19 +0000
+Subject: [PATCH] Bug 1153478 - Part 1: Add nsInlineFrame::StealFrame and make
+ it deal with being called on the wrong parent for aChild (due to lazy
+ reparenting). r=roc, a=sledru
+
+---
+ layout/generic/nsContainerFrame.cpp | 7 +++----
+ layout/generic/nsInlineFrame.cpp | 39 +++++++++++++++++++++++++++++++++++++
+ layout/generic/nsInlineFrame.h | 4 +++-
+ 3 files changed, 45 insertions(+), 5 deletions(-)
+
+diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
+index 3ffcba7..34878af 100644
+--- a/layout/generic/nsContainerFrame.cpp
++++ b/layout/generic/nsContainerFrame.cpp
+@@ -172,13 +172,12 @@ nsContainerFrame::RemoveFrame(ChildListID aListID,
+ nsIPresShell* shell = PresContext()->PresShell();
+ nsContainerFrame* lastParent = nullptr;
+ while (aOldFrame) {
+- //XXXfr probably should use StealFrame here. I'm not sure if we need to
+- // check the overflow lists atm, but we'll need a prescontext lookup
+- // for overflow containers once we can split abspos elements with
+- // inline containing blocks.
+ nsIFrame* oldFrameNextContinuation = aOldFrame->GetNextContinuation();
+ nsContainerFrame* parent =
+ static_cast<nsContainerFrame*>(aOldFrame->GetParent());
++ // Please note that 'parent' may not actually be where 'aOldFrame' lives.
++ // We really MUST use StealFrame() and nothing else here.
++ // @see nsInlineFrame::StealFrame for details.
+ parent->StealFrame(aOldFrame, true);
+ aOldFrame->Destroy();
+ aOldFrame = oldFrameNextContinuation;
+diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp
+index 526041e..a392a15 100644
+--- a/layout/generic/nsInlineFrame.cpp
++++ b/layout/generic/nsInlineFrame.cpp
+@@ -172,6 +172,45 @@ nsInlineFrame::PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+ return CONTINUE;
+ }
+
++nsresult
++nsInlineFrame::StealFrame(nsIFrame* aChild,
++ bool aForceNormal)
++{
++ if (aChild->HasAnyStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER) &&
++ !aForceNormal) {
++ return nsContainerFrame::StealFrame(aChild, aForceNormal);
++ }
++
++ nsInlineFrame* parent = this;
++ bool removed = false;
++ do {
++ removed = parent->mFrames.StartRemoveFrame(aChild);
++ if (removed) {
++ break;
++ }
++
++ // We didn't find the child in our principal child list.
++ // Maybe it's on the overflow list?
++ nsFrameList* frameList = parent->GetOverflowFrames();
++ if (frameList) {
++ removed = frameList->ContinueRemoveFrame(aChild);
++ if (frameList->IsEmpty()) {
++ parent->DestroyOverflowList();
++ }
++ if (removed) {
++ break;
++ }
++ }
++
++ // Due to our "lazy reparenting" optimization 'aChild' might not actually
++ // be on any of our child lists, but instead in one of our next-in-flows.
++ parent = static_cast<nsInlineFrame*>(parent->GetNextInFlow());
++ } while (parent);
++
++ MOZ_ASSERT(removed, "nsInlineFrame::StealFrame: can't find aChild");
++ return removed ? NS_OK : NS_ERROR_UNEXPECTED;
++}
++
+ void
+ nsInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+diff --git a/layout/generic/nsInlineFrame.h b/layout/generic/nsInlineFrame.h
+index 1a9899e..3e49241 100644
+--- a/layout/generic/nsInlineFrame.h
++++ b/layout/generic/nsInlineFrame.h
+@@ -61,7 +61,9 @@ public:
+
+ virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
+ bool aRespectClusters = true) MOZ_OVERRIDE;
+-
++
++ virtual nsresult StealFrame(nsIFrame* aChild, bool aForceNormal) MOZ_OVERRIDE;
++
+ // nsIHTMLReflow overrides
+ virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
+ InlineMinWidthData *aData) MOZ_OVERRIDE;
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2713-pt2.patch b/gnu/packages/patches/icecat-CVE-2015-2713-pt2.patch
new file mode 100644
index 0000000000..b1f2adde47
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2713-pt2.patch
@@ -0,0 +1,47 @@
+From d84ed2990dd2304fef752213f1908280ff24d77c Mon Sep 17 00:00:00 2001
+From: Mats Palmgren <mats@mozilla.com>
+Date: Thu, 16 Apr 2015 09:04:19 +0000
+Subject: [PATCH] Bug 1153478 - Part 2: Remove useless assertions. r=roc,
+ a=sledru
+
+---
+ layout/generic/nsContainerFrame.cpp | 1 -
+ layout/generic/nsInlineFrame.cpp | 3 ---
+ 2 files changed, 4 deletions(-)
+
+diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
+index 34878af..b95bddd 100644
+--- a/layout/generic/nsContainerFrame.cpp
++++ b/layout/generic/nsContainerFrame.cpp
+@@ -1516,7 +1516,6 @@ nsContainerFrame::DrainSelfOverflowList()
+ {
+ AutoFrameListPtr overflowFrames(PresContext(), StealOverflowFrames());
+ if (overflowFrames) {
+- NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
+ mFrames.AppendFrames(nullptr, *overflowFrames);
+ return true;
+ }
+diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp
+index a392a15..e0922bb 100644
+--- a/layout/generic/nsInlineFrame.cpp
++++ b/layout/generic/nsInlineFrame.cpp
+@@ -449,7 +449,6 @@ nsInlineFrame::DrainSelfOverflowListInternal(DrainFlags aFlags,
+ {
+ AutoFrameListPtr overflowFrames(PresContext(), StealOverflowFrames());
+ if (overflowFrames) {
+- NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
+ // The frames on our own overflowlist may have been pushed by a
+ // previous lazilySetParentPointer Reflow so we need to ensure the
+ // correct parent pointer. This is sometimes skipped by Reflow.
+@@ -1157,8 +1156,6 @@ nsFirstLineFrame::DrainSelfOverflowList()
+ {
+ AutoFrameListPtr overflowFrames(PresContext(), StealOverflowFrames());
+ if (overflowFrames) {
+- NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
+-
+ bool result = !overflowFrames->IsEmpty();
+ const nsFrameList::Slice& newFrames =
+ mFrames.AppendFrames(nullptr, *overflowFrames);
+--
+2.2.1
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-2716.patch b/gnu/packages/patches/icecat-CVE-2015-2716.patch
new file mode 100644
index 0000000000..ce036a0921
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-2716.patch
@@ -0,0 +1,62 @@
+From 9dcb4563847cb6e2a8112dca03d2684907f96313 Mon Sep 17 00:00:00 2001
+From: Eric Rahm <erahm@mozilla.com>
+Date: Fri, 10 Apr 2015 15:50:23 -0700
+Subject: [PATCH] Bug 1140537 - Sanity check size calculations. r=peterv,
+ a=abillings
+
+---
+ parser/expat/lib/xmlparse.c | 23 +++++++++++++++++++++--
+ 1 file changed, 21 insertions(+), 2 deletions(-)
+
+diff --git a/parser/expat/lib/xmlparse.c b/parser/expat/lib/xmlparse.c
+index 70acf1a..436b735 100644
+--- a/parser/expat/lib/xmlparse.c
++++ b/parser/expat/lib/xmlparse.c
+@@ -1651,6 +1651,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+ void * XMLCALL
+ XML_GetBuffer(XML_Parser parser, int len)
+ {
++/* BEGIN MOZILLA CHANGE (sanity check len) */
++ if (len < 0) {
++ errorCode = XML_ERROR_NO_MEMORY;
++ return NULL;
++ }
++/* END MOZILLA CHANGE */
+ switch (ps_parsing) {
+ case XML_SUSPENDED:
+ errorCode = XML_ERROR_SUSPENDED;
+@@ -1662,8 +1668,13 @@ XML_GetBuffer(XML_Parser parser, int len)
+ }
+
+ if (len > bufferLim - bufferEnd) {
+- /* FIXME avoid integer overflow */
+ int neededSize = len + (int)(bufferEnd - bufferPtr);
++/* BEGIN MOZILLA CHANGE (sanity check neededSize) */
++ if (neededSize < 0) {
++ errorCode = XML_ERROR_NO_MEMORY;
++ return NULL;
++ }
++/* END MOZILLA CHANGE */
+ #ifdef XML_CONTEXT_BYTES
+ int keep = (int)(bufferPtr - buffer);
+
+@@ -1692,7 +1703,15 @@ XML_GetBuffer(XML_Parser parser, int len)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+ bufferSize *= 2;
+- } while (bufferSize < neededSize);
++/* BEGIN MOZILLA CHANGE (prevent infinite loop on overflow) */
++ } while (bufferSize < neededSize && bufferSize > 0);
++/* END MOZILLA CHANGE */
++/* BEGIN MOZILLA CHANGE (sanity check bufferSize) */
++ if (bufferSize <= 0) {
++ errorCode = XML_ERROR_NO_MEMORY;
++ return NULL;
++ }
++/* END MOZILLA CHANGE */
+ newBuf = (char *)MALLOC(bufferSize);
+ if (newBuf == 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+--
+2.2.1
+