summary refs log tree commit diff
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
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
+