summaryrefslogtreecommitdiff
path: root/gnu/packages/patches
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages/patches')
-rw-r--r--gnu/packages/patches/bitlbee-configure-doc-fix.patch15
-rw-r--r--gnu/packages/patches/einstein-build.patch401
-rw-r--r--gnu/packages/patches/gitolite-openssh-6.8-compat.patch25
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-4477.patch37
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-7207.patch1140
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch356
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch58
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch60
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch53
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch32
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch103
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1954.patch32
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1960.patch55
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1961.patch33
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1962.patch107
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1964.patch54
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1965.patch44
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1966.patch36
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1974.patch530
-rw-r--r--gnu/packages/patches/icecat-bug-1248851.patch37
-rw-r--r--gnu/packages/patches/icecat-update-graphite2-pt2.patch861
-rw-r--r--gnu/packages/patches/ilmbase-fix-tests.patch149
-rw-r--r--gnu/packages/patches/jasper-CVE-2016-1577.patch19
-rw-r--r--gnu/packages/patches/jasper-CVE-2016-2089.patch90
-rw-r--r--gnu/packages/patches/jasper-CVE-2016-2116.patch19
-rw-r--r--gnu/packages/patches/libotr-test-auth-fix.patch15
-rw-r--r--gnu/packages/patches/mupdf-buildsystem-fix.patch69
-rw-r--r--gnu/packages/patches/openssl-c-rehash-in.patch17
-rw-r--r--gnu/packages/patches/perl-CVE-2016-2381.patch116
-rw-r--r--gnu/packages/patches/procmail-ambiguous-getline-debian.patch61
-rw-r--r--gnu/packages/patches/python-rarfile-fix-tests.patch14
-rw-r--r--gnu/packages/patches/scribus-qobject.patch17
-rw-r--r--gnu/packages/patches/vorbis-tools-CVE-2015-6749.patch44
33 files changed, 4573 insertions, 126 deletions
diff --git a/gnu/packages/patches/bitlbee-configure-doc-fix.patch b/gnu/packages/patches/bitlbee-configure-doc-fix.patch
deleted file mode 100644
index ade0b7f25c..0000000000
--- a/gnu/packages/patches/bitlbee-configure-doc-fix.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-Fix the check for the prebuilt helpfile when xsltproc is not available.
-
---- bitlbee-3.4/configure.orig 2015-03-25 18:09:10.000000000 -0400
-+++ bitlbee-3.4/configure 2015-05-20 14:51:33.627975970 -0400
-@@ -650,8 +650,8 @@
-
- if [ "$doc" = "1" ]; then
- if [ ! -e doc/user-guide/help.txt ] && \
-- ! type xmlto > /dev/null 2> /dev/null || \
-- ! type xsltproc > /dev/null 2> /dev/null
-+ (! type xmlto > /dev/null 2> /dev/null || \
-+ ! type xsltproc > /dev/null 2> /dev/null)
- then
- echo
- echo 'WARNING: Building from an unreleased source tree without prebuilt helpfile.'
diff --git a/gnu/packages/patches/einstein-build.patch b/gnu/packages/patches/einstein-build.patch
new file mode 100644
index 0000000000..b0d3087a7a
--- /dev/null
+++ b/gnu/packages/patches/einstein-build.patch
@@ -0,0 +1,401 @@
+These patches are required to build with a modern GCC; most of them
+are taken from the Debian package. Upstream has disappeared.
+
+diff -r -u einstein-2.0.orig/convert.h einstein-2.0/convert.h
+--- einstein-2.0.orig/convert.h 2005-08-14 04:40:58.000000000 +0200
++++ einstein-2.0/convert.h 2016-03-05 18:25:08.488917021 +0100
+@@ -5,6 +5,7 @@
+ #include <iostream>
+ #include <sstream>
+ #include <string>
++#include <typeinfo>
+
+ #include "exceptions.h"
+ #include "unicode.h"
+diff -r -u einstein-2.0.orig/descr.cpp einstein-2.0/descr.cpp
+--- einstein-2.0.orig/descr.cpp 2005-08-17 15:42:29.000000000 +0200
++++ einstein-2.0/descr.cpp 2016-03-05 18:29:27.960352230 +0100
+@@ -139,9 +139,9 @@
+ {
+ currentPage = 0;
+ //area.add(parentArea, false);
+- titleFont = new Font(L"nova.ttf", 26);
+- buttonFont = new Font(L"laudcn2.ttf", 14);
+- textFont = new Font(L"laudcn2.ttf", 16);
++ titleFont = new Font(L"DejaVuSans.ttf", 26);
++ buttonFont = new Font(L"DejaVuSans.ttf", 14);
++ textFont = new Font(L"DejaVuSans.ttf", 16);
+ textHeight = (int)(textFont->getHeight(L"A") * 1.0);
+ text = new TextParser(msg(L"rulesText"), *textFont, START_X, START_Y,
+ CLIENT_WIDTH, CLIENT_HEIGHT);
+diff -r -u einstein-2.0.orig/font.h einstein-2.0/font.h
+--- einstein-2.0.orig/font.h 2005-08-16 00:33:17.000000000 +0200
++++ einstein-2.0/font.h 2016-03-05 18:22:05.563794039 +0100
+@@ -3,7 +3,7 @@
+
+
+ #include <string>
+-#include <SDL_ttf.h>
++#include <SDL/SDL_ttf.h>
+
+
+ class Font
+diff -r -u einstein-2.0.orig/formatter.cpp einstein-2.0/formatter.cpp
+--- einstein-2.0.orig/formatter.cpp 2005-08-14 04:40:58.000000000 +0200
++++ einstein-2.0/formatter.cpp 2016-03-05 18:18:41.146882565 +0100
+@@ -58,7 +58,7 @@
+ if ((c.type == INT_ARG) || (c.type == STRING_ARG) ||
+ (c.type == FLOAT_ARG) || (c.type == DOUBLE_ARG))
+ {
+- int no = (int)c.data;
++ long no = (long)c.data;
+ args[no - 1] = c.type;
+ }
+ }
+@@ -123,7 +123,7 @@
+ std::wstring Formatter::format(std::vector<ArgValue*> &argValues) const
+ {
+ std::wstring s;
+- int no;
++ long no;
+
+ for (int i = 0; i < commandsCnt; i++) {
+ Command *cmd = &commands[i];
+@@ -135,8 +135,8 @@
+
+ case STRING_ARG:
+ case INT_ARG:
+- no = (int)cmd->data - 1;
+- if (no < (int)argValues.size())
++ no = (long)cmd->data - 1;
++ if (no < (long)argValues.size())
+ s += argValues[no]->format(cmd);
+ break;
+
+diff -r -u einstein-2.0.orig/game.cpp einstein-2.0/game.cpp
+--- einstein-2.0.orig/game.cpp 2005-08-23 00:44:54.000000000 +0200
++++ einstein-2.0/game.cpp 2016-03-05 18:29:27.960352230 +0100
+@@ -33,7 +33,7 @@
+ screen.draw(8, 10, tile);
+ SDL_FreeSurface(tile);
+
+- Font titleFont(L"nova.ttf", 28);
++ Font titleFont(L"DejaVuSans.ttf", 28);
+ titleFont.draw(screen.getSurface(), 20, 20, 255,255,0, true,
+ msg(L"einsteinPuzzle"));
+
+@@ -89,7 +89,7 @@
+ {
+ lastRun = elapsed = lastUpdate = 0;
+ stop();
+- font = new Font(L"luximb.ttf", 16);
++ font = new Font(L"DejaVuSans.ttf", 16);
+ }
+
+ Watch::Watch(std::istream &stream)
+@@ -97,7 +97,7 @@
+ elapsed = readInt(stream);
+ lastUpdate = 0;
+ stop();
+- font = new Font(L"luximb.ttf", 16);
++ font = new Font(L"DejaVuSans.ttf", 16);
+ }
+
+ Watch::~Watch()
+@@ -178,7 +178,7 @@
+ watch->stop();
+ Area area;
+ area.add(background, false);
+- Font font(L"laudcn2.ttf", 16);
++ Font font(L"DejaVuSans.ttf", 16);
+ area.add(new Window(280, 275, 240, 50, L"greenpattern.bmp", 6));
+ area.add(new Label(&font, 280, 275, 240, 50, Label::ALIGN_CENTER,
+ Label::ALIGN_MIDDLE, 255,255,0, msg(L"paused")));
+@@ -209,7 +209,7 @@
+ virtual void doAction() {
+ sound->play(L"applause.wav");
+ watch->stop();
+- Font font(L"laudcn2.ttf", 20);
++ Font font(L"DejaVuSans.ttf", 20);
+ showMessageWindow(gameArea, L"marble1.bmp",
+ 500, 70, &font, 255,0,0, msg(L"won"));
+ gameArea->draw();
+@@ -257,8 +257,8 @@
+ sound->play(L"glasbk2.wav");
+ bool restart = false;
+ bool newGame = false;
+- Font font(L"laudcn2.ttf", 24);
+- Font btnFont(L"laudcn2.ttf", 14);
++ Font font(L"DejaVuSans.ttf", 24);
++ Font btnFont(L"DejaVuSans.ttf", 14);
+ Area area;
+ area.add(gameArea);
+ area.add(new Window(220, 240, 360, 140, L"redpattern.bmp", 6));
+@@ -329,7 +329,7 @@
+ CheatCommand(Area *a) { gameArea = a; };
+
+ virtual void doAction() {
+- Font font(L"nova.ttf", 30);
++ Font font(L"DejaVuSans.ttf", 30);
+ showMessageWindow(gameArea, L"darkpattern.bmp",
+ 500, 100, &font, 255,255,255,
+ msg(L"iddqd"));
+@@ -475,7 +475,7 @@
+ drawWallpaper(L"rain.bmp");
+ Window window(230, 260, 340, 80, L"greenpattern.bmp", 6);
+ window.draw();
+- Font font(L"laudcn2.ttf", 16);
++ Font font(L"DejaVuSans.ttf", 16);
+ Label label(&font, 280, 275, 240, 50, Label::ALIGN_CENTER,
+ Label::ALIGN_MIDDLE, 255,255,0, msg(L"loading"));
+ label.draw();
+@@ -533,7 +533,7 @@
+ void Game::run()
+ {
+ Area area;
+- Font btnFont(L"laudcn2.ttf", 14);
++ Font btnFont(L"DejaVuSans.ttf", 14);
+
+ area.setTimer(300, watch);
+
+diff -r -u einstein-2.0.orig/main.cpp einstein-2.0/main.cpp
+--- einstein-2.0.orig/main.cpp 2005-09-26 12:32:54.000000000 +0200
++++ einstein-2.0/main.cpp 2016-03-05 18:29:27.960352230 +0100
+@@ -2,7 +2,7 @@
+ #include <iostream>
+ #include <SDL.h>
+ #include <SDL_main.h>
+-#include <SDL_ttf.h>
++#include <SDL/SDL_ttf.h>
+ #include "main.h"
+ #include "utils.h"
+ #include "storage.h"
+@@ -78,7 +78,7 @@
+ /*static void checkBetaExpire()
+ {
+ if (1124832535L + 60L*60L*24L*40L < time(NULL)) {
+- Font font(L"laudcn2.ttf", 16);
++ Font font(L"DejaVuSans.ttf", 16);
+ Area area;
+ showMessageWindow(&area, L"darkpattern.bmp",
+ 700, 100, &font, 255,255,255,
+diff -r -u einstein-2.0.orig/Makefile einstein-2.0/Makefile
+--- einstein-2.0.orig/Makefile 2005-09-25 23:20:30.000000000 +0200
++++ einstein-2.0/Makefile 2016-03-05 18:14:22.365450608 +0100
+@@ -49,10 +49,14 @@
+
+
+ $(TARGET): $(OBJECTS)
++ cd mkres && make
++ cd res && ../mkres/mkres --source resources.descr --output ../einstein.res
+ $(CXX) $(LNFLAGS) $(OBJECTS) -o $(TARGET)
+
+ clean:
+ rm -f $(OBJECTS) core* *core $(TARGET) *~
++ cd res && rm -f einstein.res
++ cd mkres && make clean
+
+ depend:
+ @makedepend $(SOURCES) 2> /dev/null
+diff -r -u einstein-2.0.orig/menu.cpp einstein-2.0/menu.cpp
+--- einstein-2.0.orig/menu.cpp 2005-09-25 22:51:00.000000000 +0200
++++ einstein-2.0/menu.cpp 2016-03-05 18:29:27.960352230 +0100
+@@ -23,11 +23,11 @@
+ SDL_Surface *title = loadImage(L"nova.bmp");
+ screen.draw(0, 0, title);
+ SDL_FreeSurface(title);
+- Font font(L"nova.ttf", 28);
++ Font font(L"DejaVuSans.ttf", 28);
+ std::wstring s(msg(L"einsteinFlowix"));
+ int width = font.getWidth(s);
+ font.draw((screen.getWidth() - width) / 2, 30, 255,255,255, true, s);
+- Font urlFont(L"luximb.ttf", 16);
++ Font urlFont(L"DejaVuSans.ttf", 16);
+ s = L"http://games.flowix.com";
+ width = urlFont.getWidth(s);
+ urlFont.draw((screen.getWidth() - width) / 2, 60, 255,255,0, true, s);
+@@ -133,9 +133,9 @@
+
+ virtual void doAction() {
+ Area area;
+- Font titleFont(L"nova.ttf", 26);
+- Font font(L"laudcn2.ttf", 14);
+- Font urlFont(L"luximb.ttf", 16);
++ Font titleFont(L"DejaVuSans.ttf", 26);
++ Font font(L"DejaVuSans.ttf", 14);
++ Font urlFont(L"DejaVuSans.ttf", 16);
+
+ #define LABEL(pos, c, f, text) area.add(new Label(&f, 220, pos, 360, 20, \
+ Label::ALIGN_CENTER, Label::ALIGN_MIDDLE, 255,255,c, text));
+@@ -171,7 +171,7 @@
+ void menu()
+ {
+ Area area;
+- Font font(L"laudcn2.ttf", 20);
++ Font font(L"DejaVuSans.ttf", 20);
+
+ area.add(new MenuBackground());
+ area.draw();
+diff -r -u einstein-2.0.orig/mkres/compressor.cpp einstein-2.0/mkres/compressor.cpp
+--- einstein-2.0.orig/mkres/compressor.cpp 2005-08-14 04:40:58.000000000 +0200
++++ einstein-2.0/mkres/compressor.cpp 2016-03-05 18:26:13.194264129 +0100
+@@ -2,6 +2,7 @@
+ #include <zlib.h>
+ #include "convert.h"
+ #include "exceptions.h"
++#include "string.h"
+
+
+ ResourceCompressor::ResourceCompressor()
+diff -r -u einstein-2.0.orig/mkres/convert.h einstein-2.0/mkres/convert.h
+--- einstein-2.0.orig/mkres/convert.h 2005-08-14 04:40:58.000000000 +0200
++++ einstein-2.0/mkres/convert.h 2016-03-05 18:25:21.479990669 +0100
+@@ -5,6 +5,7 @@
+ #include <iostream>
+ #include <sstream>
+ #include <string>
++#include <typeinfo>
+
+ #include "exceptions.h"
+ #include "unicode.h"
+diff -r -u einstein-2.0.orig/mkres/main.cpp einstein-2.0/mkres/main.cpp
+--- einstein-2.0.orig/mkres/main.cpp 2005-08-14 04:40:58.000000000 +0200
++++ einstein-2.0/mkres/main.cpp 2016-03-05 18:25:55.062765900 +0100
+@@ -1,5 +1,6 @@
+ #include "compressor.h"
+ #include "exceptions.h"
++#include "string.h"
+ #include "unicode.h"
+ #include "table.h"
+
+diff -r -u einstein-2.0.orig/mkres/unicode.cpp einstein-2.0/mkres/unicode.cpp
+--- einstein-2.0.orig/mkres/unicode.cpp 2005-08-14 04:40:58.000000000 +0200
++++ einstein-2.0/mkres/unicode.cpp 2016-03-05 18:26:28.065492890 +0100
+@@ -5,6 +5,7 @@
+ #endif
+ #include "unicode.h"
+ #include "exceptions.h"
++#include "string.h"
+
+
+ /// Returns length of wide character in utf-8
+diff -r -u einstein-2.0.orig/opensave.cpp einstein-2.0/opensave.cpp
+--- einstein-2.0.orig/opensave.cpp 2005-08-14 23:33:36.000000000 +0200
++++ einstein-2.0/opensave.cpp 2016-03-05 18:29:27.960352230 +0100
+@@ -160,7 +160,7 @@
+ static void showListWindow(SavesList &list, Command **commands,
+ const std::wstring &title, Area &area, Font *font)
+ {
+- Font titleFont(L"nova.ttf", 26);
++ Font titleFont(L"DejaVuSans.ttf", 26);
+
+ area.add(new Window(250, 90, 300, 420, L"blue.bmp"));
+ area.add(new Label(&titleFont, 250, 95, 300, 40, Label::ALIGN_CENTER,
+@@ -189,7 +189,7 @@
+
+ Area area;
+ area.add(parentArea, false);
+- Font font(L"laudcn2.ttf", 14);
++ Font font(L"DejaVuSans.ttf", 14);
+ bool saved = false;
+
+ SavesList list;
+@@ -258,7 +258,7 @@
+
+ Area area;
+ area.add(parentArea, false);
+- Font font(L"laudcn2.ttf", 14);
++ Font font(L"DejaVuSans.ttf", 14);
+
+ Game *newGame = NULL;
+
+diff -r -u einstein-2.0.orig/options.cpp einstein-2.0/options.cpp
+--- einstein-2.0.orig/options.cpp 2005-09-26 12:33:18.000000000 +0200
++++ einstein-2.0/options.cpp 2016-03-05 18:29:27.960352230 +0100
+@@ -53,8 +53,8 @@
+
+ void showOptionsWindow(Area *parentArea)
+ {
+- Font titleFont(L"nova.ttf", 26);
+- Font font(L"laudcn2.ttf", 14);
++ Font titleFont(L"DejaVuSans.ttf", 26);
++ Font font(L"DejaVuSans.ttf", 14);
+
+ bool fullscreen = (getStorage()->get(L"fullscreen", 1) != 0);
+ bool niceCursor = (getStorage()->get(L"niceCursor", 1) != 0);
+diff -r -u einstein-2.0.orig/res/resources.descr einstein-2.0/res/resources.descr
+--- einstein-2.0.orig/res/resources.descr 2005-09-25 22:51:14.000000000 +0200
++++ einstein-2.0/res/resources.descr 2016-03-05 18:30:08.563704873 +0100
+@@ -89,13 +89,11 @@
+ { name = "title.bmp" }
+ { name = "marble1.bmp" }
+ { name = "blue.bmp" }
+- { name = "luximb.ttf" }
+ { name = "redpattern.bmp" }
+ { name = "greenpattern.bmp" }
+ { name = "darkpattern.bmp" }
+ { name = "nova.bmp" }
+- { name = "nova.ttf" }
+- { name = "laudcn2.ttf" }
++ { name = "DejaVuSans.ttf" }
+ { name = "btn.bmp" }
+ { name = "rules.txt", format = "messages" group = "messages" }
+ { name = "rules_ru.txt", format = "messages" group = "messages" }
+Only in einstein-2.0/res: resources.descr.orig
+diff -r -u einstein-2.0.orig/sound.h einstein-2.0/sound.h
+--- einstein-2.0.orig/sound.h 2005-09-24 08:24:20.000000000 +0200
++++ einstein-2.0/sound.h 2016-03-05 18:22:19.314931225 +0100
+@@ -4,7 +4,7 @@
+
+ #include <string>
+ #include <map>
+-#include <SDL_mixer.h>
++#include <SDL/SDL_mixer.h>
+
+
+ class Sound
+diff -r -u einstein-2.0.orig/topscores.cpp einstein-2.0/topscores.cpp
+--- einstein-2.0.orig/topscores.cpp 2005-08-14 23:08:43.000000000 +0200
++++ einstein-2.0/topscores.cpp 2016-03-05 18:29:27.970353055 +0100
+@@ -103,9 +103,9 @@
+ ScoresWindow::ScoresWindow(int x, int y, TopScores *scores, int highlight):
+ Window(x, y, 320, 350, L"blue.bmp")
+ {
+- Font titleFont(L"nova.ttf", 26);
+- Font entryFont(L"laudcn2.ttf", 14);
+- Font timeFont(L"luximb.ttf", 14);
++ Font titleFont(L"DejaVuSans.ttf", 26);
++ Font entryFont(L"DejaVuSans.ttf", 14);
++ Font timeFont(L"DejaVuSans.ttf", 14);
+
+ std::wstring txt = msg(L"topScores");
+ int w = titleFont.getWidth(txt);
+@@ -139,7 +139,7 @@
+ {
+ Area area;
+
+- Font font(L"laudcn2.ttf", 16);
++ Font font(L"DejaVuSans.ttf", 16);
+ area.add(parentArea);
+ area.add(new ScoresWindow(240, 125, scores, highlight));
+ ExitCommand exitCmd(area);
+@@ -154,7 +154,7 @@
+ {
+ Area area;
+
+- Font font(L"laudcn2.ttf", 16);
++ Font font(L"DejaVuSans.ttf", 16);
+ area.add(parentArea);
+ area.add(new Window(170, 280, 460, 100, L"blue.bmp"));
+ Storage *storage = getStorage();
+diff -r -u einstein-2.0.orig/unicode.cpp einstein-2.0/unicode.cpp
+--- einstein-2.0.orig/unicode.cpp 2005-08-14 04:40:58.000000000 +0200
++++ einstein-2.0/unicode.cpp 2016-03-05 18:26:55.747780024 +0100
+@@ -5,6 +5,7 @@
+ #endif
+ #include "unicode.h"
+ #include "exceptions.h"
++#include "string.h"
+
+
+ /// Returns length of wide character in utf-8
diff --git a/gnu/packages/patches/gitolite-openssh-6.8-compat.patch b/gnu/packages/patches/gitolite-openssh-6.8-compat.patch
deleted file mode 100644
index d7fc2e6b12..0000000000
--- a/gnu/packages/patches/gitolite-openssh-6.8-compat.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From ed807a40c6683960e357bc995b3acf721ec088b4 Mon Sep 17 00:00:00 2001
-From: Sitaram Chamarty <sitaram@atc.tcs.com>
-Date: Thu, 19 Mar 2015 05:17:59 +0530
-Subject: [PATCH] openssh 6.8 compat
-
----
- src/triggers/post-compile/ssh-authkeys | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/triggers/post-compile/ssh-authkeys b/src/triggers/post-compile/ssh-authkeys
-index 84dda73..d5f5d8b 100755
---- a/src/triggers/post-compile/ssh-authkeys
-+++ b/src/triggers/post-compile/ssh-authkeys
-@@ -115,7 +115,7 @@ sub fp_file {
- my $f = shift;
- my $fp = `ssh-keygen -l -f '$f'`;
- chomp($fp);
-- _die "fingerprinting failed for '$f'" unless $fp =~ /([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f])+)/;
-+ _die "fingerprinting failed for '$f'" unless $fp =~ /([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f])+)/ or $fp =~ m(SHA256:([A-ZA-z0-9+/]+));
- $fp = $1;
- return $fp;
- }
---
-2.2.1
-
diff --git a/gnu/packages/patches/icecat-CVE-2015-4477.patch b/gnu/packages/patches/icecat-CVE-2015-4477.patch
new file mode 100644
index 0000000000..c010c5ecec
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-4477.patch
@@ -0,0 +1,37 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/beae8783b8c2
+
+# HG changeset patch
+# User Paul Adenot <paul@paul.cx>
+# Date 1456422965 0
+# Node ID beae8783b8c2c672da12a95c70ae663cbd0d5016
+# Parent 3a606f8182c82480f8f350b622ab55a170ec1eb6
+Bug 1179484. r=roc
+
+MozReview-Commit-ID: HNaYLyMe3sM
+
+diff --git a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
+--- a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
++++ b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
+@@ -69,16 +69,20 @@ MediaStreamAudioDestinationNode::MediaSt
+ ChannelInterpretation::Speakers)
+ , mDOMStream(DOMAudioNodeMediaStream::CreateTrackUnionStream(GetOwner(),
+ this))
+ {
+ TrackUnionStream* tus = static_cast<TrackUnionStream*>(mDOMStream->GetStream());
+ MOZ_ASSERT(tus == mDOMStream->GetStream()->AsProcessedStream());
+ tus->SetTrackIDFilter(FilterAudioNodeStreamTrack);
+
++ if (aContext->Graph() != tus->Graph()) {
++ return;
++ }
++
+ MediaStreamDestinationEngine* engine = new MediaStreamDestinationEngine(this, tus);
+ mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
+ mPort = tus->AllocateInputPort(mStream, 0);
+
+ nsIDocument* doc = aContext->GetParentObject()->GetExtantDoc();
+ if (doc) {
+ mDOMStream->CombineWithPrincipal(doc->NodePrincipal());
+ }
+
diff --git a/gnu/packages/patches/icecat-CVE-2015-7207.patch b/gnu/packages/patches/icecat-CVE-2015-7207.patch
new file mode 100644
index 0000000000..db5fc6ce66
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2015-7207.patch
@@ -0,0 +1,1140 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/532544c91db7
+
+# HG changeset patch
+# User Dragana Damjanovic <dd.mozilla@gmail.com>
+# Date 1456962626 28800
+# Node ID 532544c91db7f13c39be1b7b7c4461cd03126e9c
+# Parent f4220254d5bd0851a439467da39ba431e0ce2804
+Bug 1185256 - Save originURI to the history. r=bz ba=ritu
+
+MozReview-Commit-ID: Lvh9C84RQUc
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -1020,16 +1020,17 @@ nsDocShell::DestroyChildren()
+ //*****************************************************************************
+ // nsDocShell::nsISupports
+ //*****************************************************************************
+
+ NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
+ NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
+
+ NS_INTERFACE_MAP_BEGIN(nsDocShell)
++ NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38_2)
+ NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38)
+ NS_INTERFACE_MAP_ENTRY(nsIDocShell)
+ NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
+ NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
+ NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
+ NS_INTERFACE_MAP_ENTRY(nsIScrollable)
+ NS_INTERFACE_MAP_ENTRY(nsITextScroll)
+ NS_INTERFACE_MAP_ENTRY(nsIDocCharset)
+@@ -1372,16 +1373,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
+ return NS_OK; // JS may not handle returning of an error code
+ }
+
+ if (DoAppRedirectIfNeeded(aURI, aLoadInfo, aFirstParty)) {
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIURI> referrer;
++ nsCOMPtr<nsIURI> originalURI;
+ nsCOMPtr<nsIInputStream> postStream;
+ nsCOMPtr<nsIInputStream> headersStream;
+ nsCOMPtr<nsISupports> owner;
+ bool inheritOwner = false;
+ bool ownerIsExplicit = false;
+ bool sendReferrer = true;
+ uint32_t referrerPolicy = mozilla::net::RP_Default;
+ bool isSrcdoc = false;
+@@ -1398,16 +1400,20 @@ nsDocShell::LoadURI(nsIURI* aURI,
+ if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
+ mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
+ StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
+ }
+
+ // Extract the info from the DocShellLoadInfo struct...
+ if (aLoadInfo) {
+ aLoadInfo->GetReferrer(getter_AddRefs(referrer));
++ nsCOMPtr<nsIDocShellLoadInfo_ESR38> liESR38 = do_QueryInterface(aLoadInfo);
++ if (liESR38) {
++ liESR38->GetOriginalURI(getter_AddRefs(originalURI));
++ }
+
+ nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
+ aLoadInfo->GetLoadType(&lt);
+ // Get the appropriate loadType from nsIDocShellLoadInfo type
+ loadType = ConvertDocShellLoadInfoToLoadType(lt);
+
+ aLoadInfo->GetOwner(getter_AddRefs(owner));
+ aLoadInfo->GetInheritOwner(&inheritOwner);
+@@ -1652,34 +1658,35 @@ nsDocShell::LoadURI(nsIURI* aURI,
+ if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
+ flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
+ }
+
+ if (isSrcdoc) {
+ flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
+ }
+
+- return InternalLoad(aURI,
+- referrer,
+- referrerPolicy,
+- owner,
+- flags,
+- target.get(),
+- nullptr, // No type hint
+- NullString(), // No forced download
+- postStream,
+- headersStream,
+- loadType,
+- nullptr, // No SHEntry
+- aFirstParty,
+- srcdoc,
+- sourceDocShell,
+- baseURI,
+- nullptr, // No nsIDocShell
+- nullptr); // No nsIRequest
++ return InternalLoad2(aURI,
++ originalURI,
++ referrer,
++ referrerPolicy,
++ owner,
++ flags,
++ target.get(),
++ nullptr, // No type hint
++ NullString(), // No forced download
++ postStream,
++ headersStream,
++ loadType,
++ nullptr, // No SHEntry
++ aFirstParty,
++ srcdoc,
++ sourceDocShell,
++ baseURI,
++ nullptr, // No nsIDocShell
++ nullptr); // No nsIRequest
+ }
+
+ NS_IMETHODIMP
+ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
+ const nsACString& aContentType,
+ const nsACString& aContentCharset,
+ nsIDocShellLoadInfo* aLoadInfo)
+ {
+@@ -5398,21 +5405,21 @@ nsDocShell::LoadErrorPage(nsIURI* aURI,
+ // end of the URL, so append it last.
+ errorPageUrl.AppendLiteral("&d=");
+ errorPageUrl.AppendASCII(escapedDescription.get());
+
+ nsCOMPtr<nsIURI> errorPageURI;
+ rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+- return InternalLoad(errorPageURI, nullptr, mozilla::net::RP_Default,
+- nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr,
+- nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
+- nullptr, true, NullString(), this, nullptr, nullptr,
+- nullptr);
++ return InternalLoad2(errorPageURI, nullptr, nullptr, mozilla::net::RP_Default,
++ nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr,
++ nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
++ nullptr, true, NullString(), this, nullptr, nullptr,
++ nullptr);
+ }
+
+ NS_IMETHODIMP
+ nsDocShell::Reload(uint32_t aReloadFlags)
+ {
+ if (!IsNavigationAllowed()) {
+ return NS_OK; // JS may not handle returning of an error code
+ }
+@@ -5448,44 +5455,54 @@ nsDocShell::Reload(uint32_t aReloadFlags
+ nsCOMPtr<nsIDocument> doc(GetDocument());
+
+ // Do not inherit owner from document
+ uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
+ nsAutoString srcdoc;
+ nsIPrincipal* principal = nullptr;
+ nsAutoString contentTypeHint;
+ nsCOMPtr<nsIURI> baseURI;
++ nsCOMPtr<nsIURI> originalURI;
+ if (doc) {
+ principal = doc->NodePrincipal();
+ doc->GetContentType(contentTypeHint);
+
+ if (doc->IsSrcdocDocument()) {
+ doc->GetSrcdocData(srcdoc);
+ flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
+ baseURI = doc->GetBaseURI();
+ }
+- }
+- rv = InternalLoad(mCurrentURI,
+- mReferrerURI,
+- mReferrerPolicy,
+- principal,
+- flags,
+- nullptr, // No window target
+- NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
+- NullString(), // No forced download
+- nullptr, // No post data
+- nullptr, // No headers data
+- loadType, // Load type
+- nullptr, // No SHEntry
+- true,
+- srcdoc, // srcdoc argument for iframe
+- this, // For reloads we are the source
+- baseURI,
+- nullptr, // No nsIDocShell
+- nullptr); // No nsIRequest
++ nsCOMPtr<nsIChannel> chan = doc->GetChannel();
++ if (chan) {
++ nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
++ if (httpChan) {
++ httpChan->GetOriginalURI(getter_AddRefs(originalURI));
++ }
++ }
++ }
++
++ rv = InternalLoad2(mCurrentURI,
++ originalURI,
++ mReferrerURI,
++ mReferrerPolicy,
++ principal,
++ flags,
++ nullptr, // No window target
++ NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
++ NullString(), // No forced download
++ nullptr, // No post data
++ nullptr, // No headers data
++ loadType, // Load type
++ nullptr, // No SHEntry
++ true,
++ srcdoc, // srcdoc argument for iframe
++ this, // For reloads we are the source
++ baseURI,
++ nullptr, // No nsIDocShell
++ nullptr); // No nsIRequest
+ }
+
+ return rv;
+ }
+
+ NS_IMETHODIMP
+ nsDocShell::Stop(uint32_t aStopFlags)
+ {
+@@ -9463,27 +9480,28 @@ CopyFavicon(nsIURI* aOldURI, nsIURI* aNe
+ #endif
+ }
+
+ } // anonymous namespace
+
+ class InternalLoadEvent : public nsRunnable
+ {
+ public:
+- InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI,
++ InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI, nsIURI* aOriginalURI,
+ nsIURI* aReferrer, uint32_t aReferrerPolicy,
+ nsISupports* aOwner, uint32_t aFlags,
+ const char* aTypeHint, nsIInputStream* aPostData,
+ nsIInputStream* aHeadersData, uint32_t aLoadType,
+ nsISHEntry* aSHEntry, bool aFirstParty,
+ const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell,
+ nsIURI* aBaseURI)
+ : mSrcdoc(aSrcdoc)
+ , mDocShell(aDocShell)
+ , mURI(aURI)
++ , mOriginalURI(aOriginalURI)
+ , mReferrer(aReferrer)
+ , mReferrerPolicy(aReferrerPolicy)
+ , mOwner(aOwner)
+ , mPostData(aPostData)
+ , mHeadersData(aHeadersData)
+ , mSHEntry(aSHEntry)
+ , mFlags(aFlags)
+ , mLoadType(aLoadType)
+@@ -9494,34 +9512,36 @@ public:
+ // Make sure to keep null things null as needed
+ if (aTypeHint) {
+ mTypeHint = aTypeHint;
+ }
+ }
+
+ NS_IMETHOD Run()
+ {
+- return mDocShell->InternalLoad(mURI, mReferrer,
+- mReferrerPolicy,
+- mOwner, mFlags,
+- nullptr, mTypeHint.get(),
+- NullString(), mPostData, mHeadersData,
+- mLoadType, mSHEntry, mFirstParty,
+- mSrcdoc, mSourceDocShell, mBaseURI,
+- nullptr, nullptr);
++ return mDocShell->InternalLoad2(mURI, mOriginalURI,
++ mReferrer,
++ mReferrerPolicy,
++ mOwner, mFlags,
++ nullptr, mTypeHint.get(),
++ NullString(), mPostData, mHeadersData,
++ mLoadType, mSHEntry, mFirstParty,
++ mSrcdoc, mSourceDocShell, mBaseURI,
++ nullptr, nullptr);
+ }
+
+ private:
+ // Use IDL strings so .get() returns null by default
+ nsXPIDLString mWindowTarget;
+ nsXPIDLCString mTypeHint;
+ nsString mSrcdoc;
+
+ nsRefPtr<nsDocShell> mDocShell;
+ nsCOMPtr<nsIURI> mURI;
++ nsCOMPtr<nsIURI> mOriginalURI;
+ nsCOMPtr<nsIURI> mReferrer;
+ uint32_t mReferrerPolicy;
+ nsCOMPtr<nsISupports> mOwner;
+ nsCOMPtr<nsIInputStream> mPostData;
+ nsCOMPtr<nsIInputStream> mHeadersData;
+ nsCOMPtr<nsISHEntry> mSHEntry;
+ uint32_t mFlags;
+ uint32_t mLoadType;
+@@ -9584,16 +9604,43 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+ nsISHEntry* aSHEntry,
+ bool aFirstParty,
+ const nsAString& aSrcdoc,
+ nsIDocShell* aSourceDocShell,
+ nsIURI* aBaseURI,
+ nsIDocShell** aDocShell,
+ nsIRequest** aRequest)
+ {
++ return InternalLoad2(aURI, nullptr, aReferrer, aReferrerPolicy, aOwner,
++ aFlags, aWindowTarget, aTypeHint, aFileName, aPostData,
++ aHeadersData, aLoadType, aSHEntry, aFirstParty, aSrcdoc,
++ aSourceDocShell, aBaseURI, aDocShell, aRequest);
++}
++
++NS_IMETHODIMP
++nsDocShell::InternalLoad2(nsIURI* aURI,
++ nsIURI* aOriginalURI,
++ nsIURI* aReferrer,
++ uint32_t aReferrerPolicy,
++ nsISupports* aOwner,
++ uint32_t aFlags,
++ const char16_t* aWindowTarget,
++ const char* aTypeHint,
++ const nsAString& aFileName,
++ nsIInputStream* aPostData,
++ nsIInputStream* aHeadersData,
++ uint32_t aLoadType,
++ nsISHEntry* aSHEntry,
++ bool aFirstParty,
++ const nsAString& aSrcdoc,
++ nsIDocShell* aSourceDocShell,
++ nsIURI* aBaseURI,
++ nsIDocShell** aDocShell,
++ nsIRequest** aRequest)
++{
+ nsresult rv = NS_OK;
+ mOriginalUriString.Truncate();
+
+ #ifdef PR_LOGGING
+ if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) {
+ nsAutoCString spec;
+ if (aURI) {
+ aURI->GetSpec(spec);
+@@ -9831,34 +9878,58 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+ targetDocShell = do_QueryInterface(webNav);
+ }
+
+ //
+ // Transfer the load to the target DocShell... Pass nullptr as the
+ // window target name from to prevent recursive retargeting!
+ //
+ if (NS_SUCCEEDED(rv) && targetDocShell) {
+- rv = targetDocShell->InternalLoad(aURI,
+- aReferrer,
+- aReferrerPolicy,
+- owner,
+- aFlags,
+- nullptr, // No window target
+- aTypeHint,
+- NullString(), // No forced download
+- aPostData,
+- aHeadersData,
+- aLoadType,
+- aSHEntry,
+- aFirstParty,
+- aSrcdoc,
+- aSourceDocShell,
+- aBaseURI,
+- aDocShell,
+- aRequest);
++ nsCOMPtr<nsIDocShell_ESR38_2> dsESR38 = do_QueryInterface(targetDocShell);
++ if (dsESR38) {
++ rv = dsESR38->InternalLoad2(aURI,
++ aOriginalURI,
++ aReferrer,
++ aReferrerPolicy,
++ owner,
++ aFlags,
++ nullptr, // No window target
++ aTypeHint,
++ NullString(), // No forced download
++ aPostData,
++ aHeadersData,
++ aLoadType,
++ aSHEntry,
++ aFirstParty,
++ aSrcdoc,
++ aSourceDocShell,
++ aBaseURI,
++ aDocShell,
++ aRequest);
++ } else {
++ rv = targetDocShell->InternalLoad(aURI,
++ aReferrer,
++ aReferrerPolicy,
++ owner,
++ aFlags,
++ nullptr, // No window target
++ aTypeHint,
++ NullString(), // No forced download
++ aPostData,
++ aHeadersData,
++ aLoadType,
++ aSHEntry,
++ aFirstParty,
++ aSrcdoc,
++ aSourceDocShell,
++ aBaseURI,
++ aDocShell,
++ aRequest);
++ }
++
+ if (rv == NS_ERROR_NO_CONTENT) {
+ // XXXbz except we never reach this code!
+ if (isNewWindow) {
+ //
+ // At this point, a new window has been created, but the
+ // URI did not have any data associated with it...
+ //
+ // So, the best we can do, is to tear down the new window
+@@ -9913,17 +9984,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+ // the unload event also a replace load, so we don't
+ // create extra history entries.
+ if (LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
+ mLoadType = LOAD_NORMAL_REPLACE;
+ }
+
+ // Do this asynchronously
+ nsCOMPtr<nsIRunnable> ev =
+- new InternalLoadEvent(this, aURI, aReferrer,
++ new InternalLoadEvent(this, aURI, aOriginalURI, aReferrer,
+ aReferrerPolicy, aOwner, aFlags,
+ aTypeHint, aPostData, aHeadersData,
+ aLoadType, aSHEntry, aFirstParty, aSrcdoc,
+ aSourceDocShell, aBaseURI);
+ return NS_DispatchToCurrentThread(ev);
+ }
+
+ // Just ignore this load attempt
+@@ -10371,17 +10442,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+ }
+
+ net::PredictorLearn(aURI, nullptr,
+ nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, this);
+ net::PredictorPredict(aURI, nullptr,
+ nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
+
+ nsCOMPtr<nsIRequest> req;
+- rv = DoURILoad(aURI, aReferrer,
++ rv = DoURILoad(aURI, aOriginalURI, aReferrer,
+ !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
+ aReferrerPolicy,
+ owner, aTypeHint, aFileName, aPostData, aHeadersData,
+ aFirstParty, aDocShell, getter_AddRefs(req),
+ (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
+ (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
+ (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
+ srcdoc, aBaseURI, contentType);
+@@ -10445,16 +10516,17 @@ nsDocShell::GetInheritedPrincipal(bool a
+ return docPrincipal;
+ }
+
+ return nullptr;
+ }
+
+ nsresult
+ nsDocShell::DoURILoad(nsIURI* aURI,
++ nsIURI* aOriginalURI,
+ nsIURI* aReferrerURI,
+ bool aSendReferrer,
+ uint32_t aReferrerPolicy,
+ nsISupports* aOwner,
+ const char* aTypeHint,
+ const nsAString& aFileName,
+ nsIInputStream* aPostData,
+ nsIInputStream* aHeadersData,
+@@ -10652,17 +10724,22 @@ nsDocShell::DoURILoad(nsIURI* aURI,
+ }
+
+ // Make sure to give the caller a channel if we managed to create one
+ // This is important for correct error page/session history interaction
+ if (aRequest) {
+ NS_ADDREF(*aRequest = channel);
+ }
+
+- channel->SetOriginalURI(aURI);
++ if (aOriginalURI) {
++ channel->SetOriginalURI(aOriginalURI);
++ } else {
++ channel->SetOriginalURI(aURI);
++ }
++
+ if (aTypeHint && *aTypeHint) {
+ channel->SetContentType(nsDependentCString(aTypeHint));
+ mContentTypeHint = aTypeHint;
+ } else {
+ mContentTypeHint.Truncate();
+ }
+
+ if (!aFileName.IsVoid()) {
+@@ -11624,16 +11701,20 @@ nsDocShell::AddState(JS::Handle<JS::Valu
+
+ // AddToSessionHistory may not modify mOSHE. In case it doesn't,
+ // we'll just set mOSHE here.
+ mOSHE = newSHEntry;
+
+ } else {
+ newSHEntry = mOSHE;
+ newSHEntry->SetURI(newURI);
++ nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(newSHEntry);
++ if (entryESR38) {
++ entryESR38->SetOriginalURI(newURI);
++ }
+ }
+
+ // Step 4: Modify new/original session history entry and clear its POST
+ // data, if there is any.
+ newSHEntry->SetStateData(scContainer);
+ newSHEntry->SetPostData(nullptr);
+
+ // If this push/replaceState changed the document's current URI and the new
+@@ -11816,16 +11897,17 @@ nsDocShell::AddToSessionHistory(nsIURI*
+
+ if (!entry) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ // Get the post data & referrer
+ nsCOMPtr<nsIInputStream> inputStream;
++ nsCOMPtr<nsIURI> originalURI;
+ nsCOMPtr<nsIURI> referrerURI;
+ uint32_t referrerPolicy = mozilla::net::RP_Default;
+ nsCOMPtr<nsISupports> cacheKey;
+ nsCOMPtr<nsISupports> owner = aOwner;
+ bool expired = false;
+ bool discardLayoutState = false;
+ nsCOMPtr<nsICachingChannel> cacheChannel;
+ if (aChannel) {
+@@ -11843,16 +11925,17 @@ nsDocShell::AddToSessionHistory(nsIURI*
+ if (!httpChannel) {
+ GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
+ }
+ if (httpChannel) {
+ nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
+ if (uploadChannel) {
+ uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
+ }
++ httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
+ httpChannel->GetReferrer(getter_AddRefs(referrerURI));
+ httpChannel->GetReferrerPolicy(&referrerPolicy);
+
+ discardLayoutState = ShouldDiscardLayoutState(httpChannel);
+ }
+ aChannel->GetOwner(getter_AddRefs(owner));
+ if (!owner) {
+ nsCOMPtr<nsILoadInfo> loadInfo;
+@@ -11875,16 +11958,21 @@ nsDocShell::AddToSessionHistory(nsIURI*
+ EmptyString(), // Title
+ inputStream, // Post data stream
+ nullptr, // LayoutHistory state
+ cacheKey, // CacheKey
+ mContentTypeHint, // Content-type
+ owner, // Channel or provided owner
+ mHistoryID,
+ mDynamicallyCreated);
++
++ nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(entry);
++ if (entryESR38) {
++ entryESR38->SetOriginalURI(originalURI);
++ }
+ entry->SetReferrerURI(referrerURI);
+ entry->SetReferrerPolicy(referrerPolicy);
+ nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
+ if (inStrmChan) {
+ bool isSrcdocChannel;
+ inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
+ if (isSrcdocChannel) {
+ nsAutoString srcdoc;
+@@ -11976,25 +12064,32 @@ nsDocShell::AddToSessionHistory(nsIURI*
+ nsresult
+ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
+ {
+ if (!IsNavigationAllowed()) {
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIURI> uri;
++ nsCOMPtr<nsIURI> originalURI;
+ nsCOMPtr<nsIInputStream> postData;
+ nsCOMPtr<nsIURI> referrerURI;
+ uint32_t referrerPolicy;
+ nsAutoCString contentType;
+ nsCOMPtr<nsISupports> owner;
+
+ NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
+
+ NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
++
++ nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(aEntry);
++ if (entryESR38) {
++ NS_ENSURE_SUCCESS(entryESR38->GetOriginalURI(getter_AddRefs(originalURI)),
++ NS_ERROR_FAILURE);
++ }
+ NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
+ NS_ERROR_FAILURE);
+ NS_ENSURE_SUCCESS(aEntry->GetReferrerPolicy(&referrerPolicy),
+ NS_ERROR_FAILURE);
+ NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)),
+ NS_ERROR_FAILURE);
+ NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE);
+ NS_ENSURE_SUCCESS(aEntry->GetOwner(getter_AddRefs(owner)), NS_ERROR_FAILURE);
+@@ -12064,34 +12159,35 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
+ } else {
+ srcdoc = NullString();
+ }
+
+ // Passing nullptr as aSourceDocShell gives the same behaviour as before
+ // aSourceDocShell was introduced. According to spec we should be passing
+ // the source browsing context that was used when the history entry was
+ // first created. bug 947716 has been created to address this issue.
+- rv = InternalLoad(uri,
+- referrerURI,
+- referrerPolicy,
+- owner,
+- flags,
+- nullptr, // No window target
+- contentType.get(), // Type hint
+- NullString(), // No forced file download
+- postData, // Post data stream
+- nullptr, // No headers stream
+- aLoadType, // Load type
+- aEntry, // SHEntry
+- true,
+- srcdoc,
+- nullptr, // Source docshell, see comment above
+- baseURI,
+- nullptr, // No nsIDocShell
+- nullptr); // No nsIRequest
++ rv = InternalLoad2(uri,
++ originalURI,
++ referrerURI,
++ referrerPolicy,
++ owner,
++ flags,
++ nullptr, // No window target
++ contentType.get(), // Type hint
++ NullString(), // No forced file download
++ postData, // Post data stream
++ nullptr, // No headers stream
++ aLoadType, // Load type
++ aEntry, // SHEntry
++ true,
++ srcdoc,
++ nullptr, // Source docshell, see comment above
++ baseURI,
++ nullptr, // No nsIDocShell
++ nullptr); // No nsIRequest
+ return rv;
+ }
+
+ NS_IMETHODIMP
+ nsDocShell::GetShouldSaveLayoutState(bool* aShould)
+ {
+ *aShould = false;
+ if (mOSHE) {
+@@ -13527,35 +13623,36 @@ nsDocShell::OnLinkClickSync(nsIContent*
+ // with it under InternalLoad; we do _not_ want to change the URI
+ // our caller passed in.
+ nsCOMPtr<nsIURI> clonedURI;
+ aURI->Clone(getter_AddRefs(clonedURI));
+ if (!clonedURI) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+- nsresult rv = InternalLoad(clonedURI, // New URI
+- referer, // Referer URI
+- refererPolicy, // Referer policy
+- aContent->NodePrincipal(), // Owner is our node's
+- // principal
+- flags,
+- target.get(), // Window target
+- NS_LossyConvertUTF16toASCII(typeHint).get(),
+- aFileName, // Download as file
+- aPostDataStream, // Post data stream
+- aHeadersDataStream, // Headers stream
+- LOAD_LINK, // Load type
+- nullptr, // No SHEntry
+- true, // first party site
+- NullString(), // No srcdoc
+- this, // We are the source
+- nullptr, // baseURI not needed
+- aDocShell, // DocShell out-param
+- aRequest); // Request out-param
++ nsresult rv = InternalLoad2(clonedURI, // New URI
++ nullptr, // Original URI
++ referer, // Referer URI
++ refererPolicy, // Referer policy
++ aContent->NodePrincipal(), // Owner is our node's
++ // principal
++ flags,
++ target.get(), // Window target
++ NS_LossyConvertUTF16toASCII(typeHint).get(),
++ aFileName, // Download as file
++ aPostDataStream, // Post data stream
++ aHeadersDataStream, // Headers stream
++ LOAD_LINK, // Load type
++ nullptr, // No SHEntry
++ true, // first party site
++ NullString(), // No srcdoc
++ this, // We are the source
++ nullptr, // baseURI not needed
++ aDocShell, // DocShell out-param
++ aRequest); // Request out-param
+ if (NS_SUCCEEDED(rv)) {
+ DispatchPings(aContent, aURI, referer, refererPolicy);
+ }
+ return rv;
+ }
+
+ NS_IMETHODIMP
+ nsDocShell::OnOverLink(nsIContent* aContent,
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -132,17 +132,17 @@ enum eCharsetReloadState
+ };
+
+ //*****************************************************************************
+ //*** nsDocShell
+ //*****************************************************************************
+
+ class nsDocShell final
+ : public nsDocLoader
+- , public nsIDocShell_ESR38
++ , public nsIDocShell_ESR38_2
+ , public nsIWebNavigation
+ , public nsIBaseWindow
+ , public nsIScrollable
+ , public nsITextScroll
+ , public nsIDocCharset
+ , public nsIContentViewerContainer
+ , public nsIRefreshURI
+ , public nsIWebProgressListener
+@@ -164,16 +164,17 @@ public:
+ nsDocShell();
+
+ NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
+
+ virtual nsresult Init() override;
+
+ NS_DECL_ISUPPORTS_INHERITED
+
++ NS_DECL_NSIDOCSHELL_ESR38_2
+ NS_DECL_NSIDOCSHELL_ESR38
+ NS_DECL_NSIDOCSHELL
+ NS_DECL_NSIDOCSHELLTREEITEM
+ NS_DECL_NSIWEBNAVIGATION
+ NS_DECL_NSIBASEWINDOW
+ NS_DECL_NSISCROLLABLE
+ NS_DECL_NSITEXTSCROLL
+ NS_DECL_NSIDOCCHARSET
+@@ -312,17 +313,20 @@ protected:
+ // at the parent.
+ nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument);
+
+ // Actually open a channel and perform a URI load. Note: whatever owner is
+ // passed to this function will be set on the channel. Callers who wish to
+ // not have an owner on the channel should just pass null.
+ // If aSrcdoc is not void, the load will be considered as a srcdoc load,
+ // and the contents of aSrcdoc will be loaded instead of aURI.
++ // aOriginalURI will be set as the originalURI on the channel that does the
++ // load. If aOriginalURI is null, aURI will be set as the originalURI.
+ nsresult DoURILoad(nsIURI* aURI,
++ nsIURI* aOriginalURI,
+ nsIURI* aReferrer,
+ bool aSendReferrer,
+ uint32_t aReferrerPolicy,
+ nsISupports* aOwner,
+ const char* aTypeHint,
+ const nsAString& aFileName,
+ nsIInputStream* aPostData,
+ nsIInputStream* aHeadersData,
+diff --git a/docshell/base/nsDocShellLoadInfo.cpp b/docshell/base/nsDocShellLoadInfo.cpp
+--- a/docshell/base/nsDocShellLoadInfo.cpp
++++ b/docshell/base/nsDocShellLoadInfo.cpp
+@@ -34,16 +34,17 @@ nsDocShellLoadInfo::~nsDocShellLoadInfo(
+ // nsDocShellLoadInfo::nsISupports
+ //*****************************************************************************
+
+ NS_IMPL_ADDREF(nsDocShellLoadInfo)
+ NS_IMPL_RELEASE(nsDocShellLoadInfo)
+
+ NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo)
++ NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo_ESR38)
+ NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo)
+ NS_INTERFACE_MAP_END
+
+ //*****************************************************************************
+ // nsDocShellLoadInfo::nsIDocShellLoadInfo
+ //*****************************************************************************
+
+ NS_IMETHODIMP
+@@ -59,16 +60,33 @@ nsDocShellLoadInfo::GetReferrer(nsIURI**
+ NS_IMETHODIMP
+ nsDocShellLoadInfo::SetReferrer(nsIURI* aReferrer)
+ {
+ mReferrer = aReferrer;
+ return NS_OK;
+ }
+
+ NS_IMETHODIMP
++nsDocShellLoadInfo::GetOriginalURI(nsIURI** aOriginalURI)
++{
++ NS_ENSURE_ARG_POINTER(aOriginalURI);
++
++ *aOriginalURI = mOriginalURI;
++ NS_IF_ADDREF(*aOriginalURI);
++ return NS_OK;
++}
++
++NS_IMETHODIMP
++nsDocShellLoadInfo::SetOriginalURI(nsIURI* aOriginalURI)
++{
++ mOriginalURI = aOriginalURI;
++ return NS_OK;
++}
++
++NS_IMETHODIMP
+ nsDocShellLoadInfo::GetOwner(nsISupports** aOwner)
+ {
+ NS_ENSURE_ARG_POINTER(aOwner);
+
+ *aOwner = mOwner;
+ NS_IF_ADDREF(*aOwner);
+ return NS_OK;
+ }
+diff --git a/docshell/base/nsDocShellLoadInfo.h b/docshell/base/nsDocShellLoadInfo.h
+--- a/docshell/base/nsDocShellLoadInfo.h
++++ b/docshell/base/nsDocShellLoadInfo.h
+@@ -14,29 +14,31 @@
+ // Interfaces Needed
+ #include "nsIDocShellLoadInfo.h"
+
+ class nsIInputStream;
+ class nsISHEntry;
+ class nsIURI;
+ class nsIDocShell;
+
+-class nsDocShellLoadInfo : public nsIDocShellLoadInfo
++class nsDocShellLoadInfo : public nsIDocShellLoadInfo_ESR38
+ {
+ public:
+ nsDocShellLoadInfo();
+
+ NS_DECL_ISUPPORTS
++ NS_DECL_NSIDOCSHELLLOADINFO_ESR38
+ NS_DECL_NSIDOCSHELLLOADINFO
+
+ protected:
+ virtual ~nsDocShellLoadInfo();
+
+ protected:
+ nsCOMPtr<nsIURI> mReferrer;
++ nsCOMPtr<nsIURI> mOriginalURI;
+ nsCOMPtr<nsISupports> mOwner;
+ bool mInheritOwner;
+ bool mOwnerIsExplicit;
+ bool mSendReferrer;
+ nsDocShellInfoReferrerPolicy mReferrerPolicy;
+ nsDocShellInfoLoadType mLoadType;
+ nsCOMPtr<nsISHEntry> mSHEntry;
+ nsString mTarget;
+diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
+--- a/docshell/base/nsIDocShell.idl
++++ b/docshell/base/nsIDocShell.idl
+@@ -1059,8 +1059,66 @@ interface nsIDocShell : nsIDocShellTreeI
+ interface nsIDocShell_ESR38 : nsIDocShell
+ {
+ /**
+ * True if new child docshells should allow content retargeting.
+ * Setting allowContentRetargeting also overwrites this value.
+ */
+ [infallible] attribute boolean allowContentRetargetingOnChildren;
+ };
++
++[scriptable, builtinclass, uuid(607604b6-8fe0-4d2c-8a6c-44f5f31a6e02)]
++interface nsIDocShell_ESR38_2 : nsIDocShell_ESR38
++{
++ /**
++ * Loads the given URI. This method is identical to loadURI(...) except
++ * that its parameter list is broken out instead of being packaged inside
++ * of an nsIDocShellLoadInfo object...
++ *
++ * @param aURI - The URI to load.
++ * @param aOriginalURI - The URI to set as the originalURI on the channel
++ * that does the load. If null, aURI will be set as
++ * the originalURI.
++ * @param aReferrer - Referring URI
++ * @param aReferrerPolicy - Referrer policy
++ * @param aOwner - Owner (security principal)
++ * @param aInheritOwner - Flag indicating whether the owner of the current
++ * document should be inherited if aOwner is null.
++ * @param aStopActiveDoc - Flag indicating whether loading the current
++ * document should be stopped.
++ * @param aWindowTarget - Window target for the load.
++ * @param aTypeHint - A hint as to the content-type of the resulting
++ * data. May be null or empty if no hint.
++ * @param aFileName - Non-null when the link should be downloaded as
++ the given filename.
++ * @param aPostDataStream - Post data stream (if POSTing)
++ * @param aHeadersStream - Stream containing "extra" request headers...
++ * @param aLoadFlags - Flags to modify load behaviour. Flags are defined
++ * in nsIWebNavigation.
++ * @param aSHEntry - Active Session History entry (if loading from SH)
++ * @param aSrcdoc When INTERNAL_LOAD_FLAGS_IS_SRCDOC is set, the
++ * contents of this parameter will be loaded instead
++ * of aURI.
++ * @param aSourceDocShell - The source browsing context for the navigation.
++ * @param aBaseURI - The base URI to be used for the load. Set in
++ * srcdoc loads as it cannot otherwise be inferred
++ * in certain situations such as view-source.
++ */
++ [noscript]void internalLoad2(in nsIURI aURI,
++ in nsIURI aOriginalURI,
++ in nsIURI aReferrer,
++ in unsigned long aReferrerPolicy,
++ in nsISupports aOwner,
++ in uint32_t aFlags,
++ in wstring aWindowTarget,
++ in string aTypeHint,
++ in AString aFileName,
++ in nsIInputStream aPostDataStream,
++ in nsIInputStream aHeadersStream,
++ in unsigned long aLoadFlags,
++ in nsISHEntry aSHEntry,
++ in boolean firstParty,
++ in AString aSrcdoc,
++ in nsIDocShell aSourceDocShell,
++ in nsIURI aBaseURI,
++ out nsIDocShell aDocShell,
++ out nsIRequest aRequest);
++};
+diff --git a/docshell/base/nsIDocShellLoadInfo.idl b/docshell/base/nsIDocShellLoadInfo.idl
+--- a/docshell/base/nsIDocShellLoadInfo.idl
++++ b/docshell/base/nsIDocShellLoadInfo.idl
+@@ -106,8 +106,17 @@ interface nsIDocShellLoadInfo : nsISuppo
+ attribute nsIDocShell sourceDocShell;
+
+ /**
+ * Used for srcdoc loads to give view-source knowledge of the load's base
+ * URI as this information isn't embedded in the load's URI.
+ */
+ attribute nsIURI baseURI;
+ };
++
++[scriptable, uuid(9d3bc466-5efe-414d-ae8b-3830b45877bb)]
++interface nsIDocShellLoadInfo_ESR38 : nsIDocShellLoadInfo
++{
++ /**
++ * The originalURI to be passed to nsIDocShell.internalLoad. May be null.
++ */
++ attribute nsIURI originalURI;
++};
+diff --git a/docshell/shistory/public/nsISHEntry.idl b/docshell/shistory/public/nsISHEntry.idl
+--- a/docshell/shistory/public/nsISHEntry.idl
++++ b/docshell/shistory/public/nsISHEntry.idl
+@@ -319,8 +319,18 @@ interface nsISHEntryInternal : nsISuppor
+ #define NS_SHENTRY_CID \
+ {0xbfd1a791, 0xad9f, 0x11d3, {0xbd, 0xc7, 0x0, 0x50, 0x4, 0xa, 0x9b, 0x44}}
+
+ #define NS_SHENTRY_CONTRACTID \
+ "@mozilla.org/browser/session-history-entry;1"
+
+ %}
+
++[scriptable, uuid(e45ab6ef-3485-449c-b91c-0846b2bf6faf)]
++interface nsISHEntry_ESR38 : nsISHEntry
++{
++ /**
++ * A readonly property that returns the original URI of the current entry.
++ * If an entry is the result of a redirect this attribute holds original
++ * URI. The object returned is of type nsIURI
++ */
++ attribute nsIURI originalURI;
++};
+diff --git a/docshell/shistory/src/nsSHEntry.cpp b/docshell/shistory/src/nsSHEntry.cpp
+--- a/docshell/shistory/src/nsSHEntry.cpp
++++ b/docshell/shistory/src/nsSHEntry.cpp
+@@ -38,16 +38,17 @@ nsSHEntry::nsSHEntry()
+ , mIsSrcdocEntry(false)
+ {
+ mShared = new nsSHEntryShared();
+ }
+
+ nsSHEntry::nsSHEntry(const nsSHEntry &other)
+ : mShared(other.mShared)
+ , mURI(other.mURI)
++ , mOriginalURI(other.mOriginalURI)
+ , mReferrerURI(other.mReferrerURI)
+ , mReferrerPolicy(other.mReferrerPolicy)
+ , mTitle(other.mTitle)
+ , mPostData(other.mPostData)
+ , mLoadType(0) // XXX why not copy?
+ , mID(other.mID)
+ , mScrollPositionX(0) // XXX why not copy?
+ , mScrollPositionY(0) // XXX why not copy?
+@@ -74,17 +75,17 @@ nsSHEntry::~nsSHEntry()
+ // Null out the mParent pointers on all our kids.
+ mChildren.EnumerateForwards(ClearParentPtr, nullptr);
+ }
+
+ //*****************************************************************************
+ // nsSHEntry: nsISupports
+ //*****************************************************************************
+
+-NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
++NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry_ESR38, nsISHEntry, nsISHEntryInternal)
+
+ //*****************************************************************************
+ // nsSHEntry: nsISHEntry
+ //*****************************************************************************
+
+ NS_IMETHODIMP nsSHEntry::SetScrollPosition(int32_t x, int32_t y)
+ {
+ mScrollPositionX = x;
+@@ -119,16 +120,29 @@ NS_IMETHODIMP nsSHEntry::GetURI(nsIURI**
+ }
+
+ NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI)
+ {
+ mURI = aURI;
+ return NS_OK;
+ }
+
++NS_IMETHODIMP nsSHEntry::GetOriginalURI(nsIURI** aOriginalURI)
++{
++ *aOriginalURI = mOriginalURI;
++ NS_IF_ADDREF(*aOriginalURI);
++ return NS_OK;
++}
++
++NS_IMETHODIMP nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI)
++{
++ mOriginalURI = aOriginalURI;
++ return NS_OK;
++}
++
+ NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI)
+ {
+ *aReferrerURI = mReferrerURI;
+ NS_IF_ADDREF(*aReferrerURI);
+ return NS_OK;
+ }
+
+ NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
+diff --git a/docshell/shistory/src/nsSHEntry.h b/docshell/shistory/src/nsSHEntry.h
+--- a/docshell/shistory/src/nsSHEntry.h
++++ b/docshell/shistory/src/nsSHEntry.h
+@@ -17,25 +17,26 @@
+ // Interfaces needed
+ #include "nsISHEntry.h"
+ #include "nsISHContainer.h"
+
+ class nsSHEntryShared;
+ class nsIInputStream;
+ class nsIURI;
+
+-class nsSHEntry final : public nsISHEntry,
++class nsSHEntry final : public nsISHEntry_ESR38,
+ public nsISHContainer,
+ public nsISHEntryInternal
+ {
+ public:
+ nsSHEntry();
+ nsSHEntry(const nsSHEntry &other);
+
+ NS_DECL_ISUPPORTS
++ NS_DECL_NSISHENTRY_ESR38
+ NS_DECL_NSISHENTRY
+ NS_DECL_NSISHENTRYINTERNAL
+ NS_DECL_NSISHCONTAINER
+
+ void DropPresentationState();
+
+ static nsresult Startup();
+ static void Shutdown();
+@@ -44,16 +45,17 @@ private:
+ ~nsSHEntry();
+
+ // We share the state in here with other SHEntries which correspond to the
+ // same document.
+ nsRefPtr<nsSHEntryShared> mShared;
+
+ // See nsSHEntry.idl for comments on these members.
+ nsCOMPtr<nsIURI> mURI;
++ nsCOMPtr<nsIURI> mOriginalURI;
+ nsCOMPtr<nsIURI> mReferrerURI;
+ uint32_t mReferrerPolicy;
+ nsString mTitle;
+ nsCOMPtr<nsIInputStream> mPostData;
+ uint32_t mLoadType;
+ uint32_t mID;
+ int32_t mScrollPositionX;
+ int32_t mScrollPositionY;
+diff --git a/docshell/shistory/src/nsSHistory.cpp b/docshell/shistory/src/nsSHistory.cpp
+--- a/docshell/shistory/src/nsSHistory.cpp
++++ b/docshell/shistory/src/nsSHistory.cpp
+@@ -1779,16 +1779,26 @@ nsSHistory::InitiateLoad(nsISHEntry * aF
+ * so that proper loadType is maintained through out a frameset
+ */
+ aFrameEntry->SetLoadType(aLoadType);
+ aFrameDS->CreateLoadInfo (getter_AddRefs(loadInfo));
+
+ loadInfo->SetLoadType(aLoadType);
+ loadInfo->SetSHEntry(aFrameEntry);
+
++ nsCOMPtr<nsIURI> originalURI;
++ nsCOMPtr<nsISHEntry_ESR38> feESR38 = do_QueryInterface(aFrameEntry);
++ if (feESR38) {
++ feESR38->GetOriginalURI(getter_AddRefs(originalURI));
++ }
++ nsCOMPtr<nsIDocShellLoadInfo_ESR38> liESR38 = do_QueryInterface(loadInfo);
++ if (liESR38) {
++ liESR38->SetOriginalURI(originalURI);
++ }
++
+ nsCOMPtr<nsIURI> nextURI;
+ aFrameEntry->GetURI(getter_AddRefs(nextURI));
+ // Time to initiate a document load
+ return aFrameDS->LoadURI(nextURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, false);
+
+ }
+
+
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch
new file mode 100644
index 0000000000..2b711b1761
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch
@@ -0,0 +1,356 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/c1d67bd4c993
+
+# HG changeset patch
+# User Timothy Nikkel <tnikkel@gmail.com>
+# Date 1454023801 21600
+# Node ID c1d67bd4c993b9e344c68954e6f0392c82b81e38
+# Parent 530559abe159d3c23f078d673d30ff03d9c244e2
+Bug 1224979 - Check if we compute usable filters for the downscaler, and if not put the downscaler in error state so it's not used. r=edwin, a=al
+
+diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp
+new file mode 100644
+--- /dev/null
++++ b/image/Downscaler.cpp
+@@ -0,0 +1,340 @@
++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ *
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#include "Downscaler.h"
++
++#include <algorithm>
++#include <ctime>
++#include "gfxPrefs.h"
++#include "image_operations.h"
++#include "mozilla/SSE.h"
++#include "convolver.h"
++#include "skia/include/core/SkTypes.h"
++
++using std::max;
++using std::swap;
++
++namespace mozilla {
++namespace image {
++
++Downscaler::Downscaler(const nsIntSize& aTargetSize)
++ : mTargetSize(aTargetSize)
++ , mOutputBuffer(nullptr)
++ , mXFilter(MakeUnique<skia::ConvolutionFilter1D>())
++ , mYFilter(MakeUnique<skia::ConvolutionFilter1D>())
++ , mWindowCapacity(0)
++ , mHasAlpha(true)
++ , mFlipVertically(false)
++{
++ MOZ_ASSERT(gfxPrefs::ImageDownscaleDuringDecodeEnabled(),
++ "Downscaling even though downscale-during-decode is disabled?");
++ MOZ_ASSERT(mTargetSize.width > 0 && mTargetSize.height > 0,
++ "Invalid target size");
++}
++
++Downscaler::~Downscaler()
++{
++ ReleaseWindow();
++}
++
++void
++Downscaler::ReleaseWindow()
++{
++ if (!mWindow) {
++ return;
++ }
++
++ for (int32_t i = 0; i < mWindowCapacity; ++i) {
++ delete[] mWindow[i];
++ }
++
++ mWindow = nullptr;
++ mWindowCapacity = 0;
++}
++
++nsresult
++Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
++ const Maybe<nsIntRect>& aFrameRect,
++ uint8_t* aOutputBuffer,
++ bool aHasAlpha,
++ bool aFlipVertically /* = false */)
++{
++ MOZ_ASSERT(aOutputBuffer);
++ MOZ_ASSERT(mTargetSize != aOriginalSize,
++ "Created a downscaler, but not downscaling?");
++ MOZ_ASSERT(mTargetSize.width <= aOriginalSize.width,
++ "Created a downscaler, but width is larger");
++ MOZ_ASSERT(mTargetSize.height <= aOriginalSize.height,
++ "Created a downscaler, but height is larger");
++ MOZ_ASSERT(aOriginalSize.width > 0 && aOriginalSize.height > 0,
++ "Invalid original size");
++
++ mFrameRect = aFrameRect.valueOr(nsIntRect(nsIntPoint(), aOriginalSize));
++ MOZ_ASSERT(mFrameRect.x >= 0 && mFrameRect.y >= 0 &&
++ mFrameRect.width >= 0 && mFrameRect.height >= 0,
++ "Frame rect must have non-negative components");
++ MOZ_ASSERT(nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
++ .Contains(mFrameRect),
++ "Frame rect must fit inside image");
++ MOZ_ASSERT_IF(!nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
++ .IsEqualEdges(mFrameRect),
++ aHasAlpha);
++
++ mOriginalSize = aOriginalSize;
++ mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
++ double(mOriginalSize.height) / mTargetSize.height);
++ mOutputBuffer = aOutputBuffer;
++ mHasAlpha = aHasAlpha;
++ mFlipVertically = aFlipVertically;
++
++ ReleaseWindow();
++
++ auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
++
++ skia::resize::ComputeFilters(resizeMethod,
++ mOriginalSize.width, mTargetSize.width,
++ 0, mTargetSize.width,
++ mXFilter.get());
++
++ if (mXFilter->max_filter() <= 0 || mXFilter->num_values() != mTargetSize.width) {
++ NS_WARNING("Failed to compute filters for image downscaling");
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
++
++ skia::resize::ComputeFilters(resizeMethod,
++ mOriginalSize.height, mTargetSize.height,
++ 0, mTargetSize.height,
++ mYFilter.get());
++
++ if (mYFilter->max_filter() <= 0 || mYFilter->num_values() != mTargetSize.height) {
++ NS_WARNING("Failed to compute filters for image downscaling");
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
++
++ // Allocate the buffer, which contains scanlines of the original image.
++ // pad by 15 to handle overreads by the simd code
++ size_t bufferLen = mOriginalSize.width * sizeof(uint32_t) + 15;
++ mRowBuffer.reset(new (fallible) uint8_t[bufferLen]);
++ if (MOZ_UNLIKELY(!mRowBuffer)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
++
++ // Zero buffer to keep valgrind happy.
++ memset(mRowBuffer.get(), 0, bufferLen);
++
++ // Allocate the window, which contains horizontally downscaled scanlines. (We
++ // can store scanlines which are already downscale because our downscaling
++ // filter is separable.)
++ mWindowCapacity = mYFilter->max_filter();
++ mWindow.reset(new (fallible) uint8_t*[mWindowCapacity]);
++ if (MOZ_UNLIKELY(!mWindow)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
++
++ bool anyAllocationFailed = false;
++ // pad by 15 to handle overreads by the simd code
++ const int rowSize = mTargetSize.width * sizeof(uint32_t) + 15;
++ for (int32_t i = 0; i < mWindowCapacity; ++i) {
++ mWindow[i] = new (fallible) uint8_t[rowSize];
++ anyAllocationFailed = anyAllocationFailed || mWindow[i] == nullptr;
++ }
++
++ if (MOZ_UNLIKELY(anyAllocationFailed)) {
++ // We intentionally iterate through the entire array even if an allocation
++ // fails, to ensure that all the pointers in it are either valid or nullptr.
++ // That in turn ensures that ReleaseWindow() can clean up correctly.
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
++
++ ResetForNextProgressivePass();
++
++ return NS_OK;
++}
++
++void
++Downscaler::SkipToRow(int32_t aRow)
++{
++ if (mCurrentInLine < aRow) {
++ ClearRow();
++ do {
++ CommitRow();
++ } while (mCurrentInLine < aRow);
++ }
++}
++
++void
++Downscaler::ResetForNextProgressivePass()
++{
++ mPrevInvalidatedLine = 0;
++ mCurrentOutLine = 0;
++ mCurrentInLine = 0;
++ mLinesInBuffer = 0;
++
++ if (mFrameRect.IsEmpty()) {
++ // Our frame rect is zero size; commit rows until the end of the image.
++ SkipToRow(mOriginalSize.height - 1);
++ } else {
++ // If we have a vertical offset, commit rows to shift us past it.
++ SkipToRow(mFrameRect.y);
++ }
++}
++
++static void
++GetFilterOffsetAndLength(UniquePtr<skia::ConvolutionFilter1D>& aFilter,
++ int32_t aOutputImagePosition,
++ int32_t* aFilterOffsetOut,
++ int32_t* aFilterLengthOut)
++{
++ MOZ_ASSERT(aOutputImagePosition < aFilter->num_values());
++ aFilter->FilterForValue(aOutputImagePosition,
++ aFilterOffsetOut,
++ aFilterLengthOut);
++}
++
++void
++Downscaler::ClearRow(uint32_t aStartingAtCol)
++{
++ MOZ_ASSERT(int64_t(mOriginalSize.width) > int64_t(aStartingAtCol));
++ uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
++ * sizeof(uint32_t);
++ memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
++ 0, bytesToClear);
++}
++
++void
++Downscaler::CommitRow()
++{
++ MOZ_ASSERT(mOutputBuffer, "Should have a current frame");
++ MOZ_ASSERT(mCurrentInLine < mOriginalSize.height, "Past end of input");
++
++ if (mCurrentOutLine < mTargetSize.height) {
++ int32_t filterOffset = 0;
++ int32_t filterLength = 0;
++ GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
++ &filterOffset, &filterLength);
++
++ int32_t inLineToRead = filterOffset + mLinesInBuffer;
++ MOZ_ASSERT(mCurrentInLine <= inLineToRead, "Reading past end of input");
++ if (mCurrentInLine == inLineToRead) {
++ skia::ConvolveHorizontally(mRowBuffer.get(), *mXFilter,
++ mWindow[mLinesInBuffer++], mHasAlpha,
++ supports_sse2());
++ }
++
++ MOZ_ASSERT(mCurrentOutLine < mTargetSize.height,
++ "Writing past end of output");
++
++ while (mLinesInBuffer == filterLength) {
++ DownscaleInputLine();
++
++ if (mCurrentOutLine == mTargetSize.height) {
++ break; // We're done.
++ }
++
++ GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
++ &filterOffset, &filterLength);
++ }
++ }
++
++ mCurrentInLine += 1;
++
++ // If we're at the end of the part of the original image that has data, commit
++ // rows to shift us to the end.
++ if (mCurrentInLine == (mFrameRect.y + mFrameRect.height)) {
++ SkipToRow(mOriginalSize.height - 1);
++ }
++}
++
++bool
++Downscaler::HasInvalidation() const
++{
++ return mCurrentOutLine > mPrevInvalidatedLine;
++}
++
++DownscalerInvalidRect
++Downscaler::TakeInvalidRect()
++{
++ if (MOZ_UNLIKELY(!HasInvalidation())) {
++ return DownscalerInvalidRect();
++ }
++
++ DownscalerInvalidRect invalidRect;
++
++ // Compute the target size invalid rect.
++ if (mFlipVertically) {
++ // We need to flip it. This will implicitly flip the original size invalid
++ // rect, since we compute it by scaling this rect.
++ invalidRect.mTargetSizeRect =
++ IntRect(0, mTargetSize.height - mCurrentOutLine,
++ mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
++ } else {
++ invalidRect.mTargetSizeRect =
++ IntRect(0, mPrevInvalidatedLine,
++ mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
++ }
++
++ mPrevInvalidatedLine = mCurrentOutLine;
++
++ // Compute the original size invalid rect.
++ invalidRect.mOriginalSizeRect = invalidRect.mTargetSizeRect;
++ invalidRect.mOriginalSizeRect.ScaleRoundOut(mScale.width, mScale.height);
++
++ return invalidRect;
++}
++
++void
++Downscaler::DownscaleInputLine()
++{
++ typedef skia::ConvolutionFilter1D::Fixed FilterValue;
++
++ MOZ_ASSERT(mOutputBuffer);
++ MOZ_ASSERT(mCurrentOutLine < mTargetSize.height,
++ "Writing past end of output");
++
++ int32_t filterOffset = 0;
++ int32_t filterLength = 0;
++ MOZ_ASSERT(mCurrentOutLine < mYFilter->num_values());
++ auto filterValues =
++ mYFilter->FilterForValue(mCurrentOutLine, &filterOffset, &filterLength);
++
++ int32_t currentOutLine = mFlipVertically
++ ? mTargetSize.height - (mCurrentOutLine + 1)
++ : mCurrentOutLine;
++ MOZ_ASSERT(currentOutLine >= 0);
++
++ uint8_t* outputLine =
++ &mOutputBuffer[currentOutLine * mTargetSize.width * sizeof(uint32_t)];
++ skia::ConvolveVertically(static_cast<const FilterValue*>(filterValues),
++ filterLength, mWindow.get(), mXFilter->num_values(),
++ outputLine, mHasAlpha, supports_sse2());
++
++ mCurrentOutLine += 1;
++
++ if (mCurrentOutLine == mTargetSize.height) {
++ // We're done.
++ return;
++ }
++
++ int32_t newFilterOffset = 0;
++ int32_t newFilterLength = 0;
++ GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
++ &newFilterOffset, &newFilterLength);
++
++ int diff = newFilterOffset - filterOffset;
++ MOZ_ASSERT(diff >= 0, "Moving backwards in the filter?");
++
++ // Shift the buffer. We're just moving pointers here, so this is cheap.
++ mLinesInBuffer -= diff;
++ mLinesInBuffer = max(mLinesInBuffer, 0);
++ for (int32_t i = 0; i < mLinesInBuffer; ++i) {
++ swap(mWindow[i], mWindow[filterLength - mLinesInBuffer + i]);
++ }
++}
++
++
++
++} // namespace image
++} // namespace mozilla
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch
new file mode 100644
index 0000000000..e01b5eaf2f
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch
@@ -0,0 +1,58 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/9719b71d72dd
+
+# HG changeset patch
+# User Byron Campen [:bwc] <docfaraday@gmail.com>
+# Date 1454100887 21600
+# Node ID 9719b71d72dd2a3c5ee12ace156af2a63d9595ac
+# Parent b68673d974a10f65390f80b36d4307eb31e44669
+Bug 1234578 - Assert if PCM is destroyed improperly. r=rjesup, a=sylvestre
+
+diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
++++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+@@ -712,16 +712,18 @@ PeerConnectionMedia::SelfDestruct_m()
+ {
+ CSFLogDebug(logTag, "%s: ", __FUNCTION__);
+
+ ASSERT_ON_THREAD(mMainThread);
+
+ mLocalSourceStreams.Clear();
+ mRemoteSourceStreams.Clear();
+
++ mMainThread = nullptr;
++
+ // Final self-destruct.
+ this->Release();
+ }
+
+ void
+ PeerConnectionMedia::ShutdownMediaTransport_s()
+ {
+ ASSERT_ON_THREAD(mSTSThread);
+diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
++++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+@@ -210,17 +210,20 @@ class RemoteSourceStreamInfo : public So
+ std::vector<std::string> mTrackIdMap;
+
+ // True iff SetPullEnabled(true) has been called on the DOMMediaStream. This
+ // happens when offer/answer concludes.
+ bool mReceiving;
+ };
+
+ class PeerConnectionMedia : public sigslot::has_slots<> {
+- ~PeerConnectionMedia() {}
++ ~PeerConnectionMedia()
++ {
++ MOZ_RELEASE_ASSERT(!mMainThread);
++ }
+
+ public:
+ explicit PeerConnectionMedia(PeerConnectionImpl *parent);
+
+ PeerConnectionImpl* GetPC() { return mParent; }
+ nsresult Init(const std::vector<NrIceStunServer>& stun_servers,
+ const std::vector<NrIceTurnServer>& turn_servers);
+ // WARNING: This destroys the object!
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch
new file mode 100644
index 0000000000..96b83c118c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch
@@ -0,0 +1,60 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/2839062f84fb
+
+# HG changeset patch
+# User Jan de Mooij <jdemooij@mozilla.com>
+# Date 1455119320 -3600
+# Node ID 2839062f84fb6cba2781ea8d59150f13d4813ddc
+# Parent 185b233ea03f3811404e3979b65ec86b29d13555
+Bug 1242279 - r=bhackett1024 a=sylvestre
+
+diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
+--- a/js/src/vm/TypeInference.cpp
++++ b/js/src/vm/TypeInference.cpp
+@@ -3961,16 +3961,22 @@ JSScript::maybeSweepTypes(AutoClearTypeI
+
+ unsigned num = TypeScript::NumTypeSets(this);
+ StackTypeSet* typeArray = types_->typeArray();
+
+ // Remove constraints and references to dead objects from stack type sets.
+ for (unsigned i = 0; i < num; i++)
+ typeArray[i].sweep(zone(), *oom);
+
++ if (oom->hadOOM()) {
++ // It's possible we OOM'd while copying freeze constraints, so they
++ // need to be regenerated.
++ hasFreezeConstraints_ = false;
++ }
++
+ // Update the recompile indexes in any IonScripts still on the script.
+ if (hasIonScript())
+ ionScript()->recompileInfoRef().shouldSweep(types);
+ }
+
+ void
+ TypeScript::destroy()
+ {
+diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h
+--- a/js/src/vm/TypeInference.h
++++ b/js/src/vm/TypeInference.h
+@@ -566,16 +566,19 @@ class AutoClearTypeInferenceStateOnOOM
+ : zone(zone), oom(false)
+ {}
+
+ ~AutoClearTypeInferenceStateOnOOM();
+
+ void setOOM() {
+ oom = true;
+ }
++ bool hadOOM() const {
++ return oom;
++ }
+ };
+
+ /* Superclass common to stack and heap type sets. */
+ class ConstraintTypeSet : public TypeSet
+ {
+ public:
+ /* Chain of constraints which propagate changes out from this type set. */
+ TypeConstraint* constraintList;
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch
new file mode 100644
index 0000000000..4eeb2377b0
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch
@@ -0,0 +1,53 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/9dd60e798819
+
+# HG changeset patch
+# User Olli Pettay <bugs@pettay.fi>
+# Date 1455204078 -3600
+# Node ID 9dd60e798819fe2ebf1e5bd36aa9006ecd2f82c9
+# Parent c1d67bd4c993b9e344c68954e6f0392c82b81e38
+Bug 1244250 - r=mats, a=al
+
+diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp
+--- a/layout/style/nsAnimationManager.cpp
++++ b/layout/style/nsAnimationManager.cpp
+@@ -715,16 +715,17 @@ nsAnimationManager::FlushAnimations(Flus
+ }
+
+ DispatchEvents(); // may destroy us
+ }
+
+ void
+ nsAnimationManager::DoDispatchEvents()
+ {
++ nsRefPtr<nsAnimationManager> kungFuDeathGrip(this);
+ EventArray events;
+ mPendingEvents.SwapElements(events);
+ for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) {
+ AnimationEventInfo &info = events[i];
+ EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
+
+ if (!mPresContext) {
+ break;
+diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp
+--- a/layout/style/nsTransitionManager.cpp
++++ b/layout/style/nsTransitionManager.cpp
+@@ -753,16 +753,17 @@ nsTransitionManager::FlushTransitions(Fl
+ }
+ }
+ }
+
+ if (didThrottle) {
+ mPresContext->Document()->SetNeedStyleFlush();
+ }
+
++ nsRefPtr<nsTransitionManager> kungFuDeathGrip(this);
+ for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) {
+ TransitionEventInfo &info = events[i];
+ EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
+
+ if (!mPresContext) {
+ break;
+ }
+ }
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch
new file mode 100644
index 0000000000..d222feff2a
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch
@@ -0,0 +1,32 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/1dd0ca8e70bd
+
+# HG changeset patch
+# User Nicolas B. Pierron <nicolas.b.pierron@mozilla.com>
+# Date 1456161361 0
+# Node ID 1dd0ca8e70bd77b6fd93f36cc4e9c2cebfe8ba0a
+# Parent 95ff874886905ef46a7bbc760981d15ad0831096
+Bug 1221872 - ValueNumbering: Set the dominator index of fixup blocks when they are created. r=sunfish, a=ritu
+
+diff --git a/js/src/jit/ValueNumbering.cpp b/js/src/jit/ValueNumbering.cpp
+--- a/js/src/jit/ValueNumbering.cpp
++++ b/js/src/jit/ValueNumbering.cpp
+@@ -433,16 +433,17 @@ ValueNumberer::fixupOSROnlyLoop(MBasicBl
+ MBasicBlock* fake = MBasicBlock::NewAsmJS(graph_, block->info(),
+ nullptr, MBasicBlock::NORMAL);
+ if (fake == nullptr)
+ return false;
+
+ graph_.insertBlockBefore(block, fake);
+ fake->setImmediateDominator(fake);
+ fake->addNumDominated(1);
++ fake->setDomIndex(fake->id());
+
+ // Create zero-input phis to use as inputs for any phis in |block|.
+ // Again, this is a little odd, but it's the least-odd thing we can do
+ // without significant complexity.
+ for (MPhiIterator iter(block->phisBegin()), end(block->phisEnd()); iter != end; ++iter) {
+ MPhi* phi = *iter;
+ MPhi* fakePhi = MPhi::New(graph_.alloc(), phi->type());
+ fake->addPhi(fakePhi);
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch
new file mode 100644
index 0000000000..3de568493b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch
@@ -0,0 +1,103 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/6f4d51302387
+
+# HG changeset patch
+# User Andrew McCreight <continuation@gmail.com>
+# Date 1456273423 28800
+# Node ID 6f4d5130238790fa5810c76ffeb9eccc65efa8c9
+# Parent 70f6c59d9d73a5edefd216b48ca74a931da12cf1
+Bug 1249685 - Use more nsCOMPtrs for stack variables in DOM code. r=smaug, a=ritu
+
+diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp
+--- a/dom/base/nsRange.cpp
++++ b/dom/base/nsRange.cpp
+@@ -1985,17 +1985,17 @@ nsRange::CutContents(DocumentFragment**
+ rv = closestAncestor ? PrependChild(closestAncestor, nodeToResult)
+ : PrependChild(commonCloneAncestor, nodeToResult);
+ NS_ENSURE_SUCCESS(rv, rv);
+ NS_ENSURE_STATE(!guard.Mutated(parent ? 2 : 1) ||
+ ValidateCurrentNode(this, iter));
+ } else if (nodeToResult) {
+ nsMutationGuard guard;
+ nsCOMPtr<nsINode> node = nodeToResult;
+- nsINode* parent = node->GetParentNode();
++ nsCOMPtr<nsINode> parent = node->GetParentNode();
+ if (parent) {
+ mozilla::ErrorResult error;
+ parent->RemoveChild(*node, error);
+ NS_ENSURE_FALSE(error.Failed(), error.ErrorCode());
+ }
+ NS_ENSURE_STATE(!guard.Mutated(1) ||
+ ValidateCurrentNode(this, iter));
+ }
+diff --git a/dom/base/nsTreeSanitizer.cpp b/dom/base/nsTreeSanitizer.cpp
+--- a/dom/base/nsTreeSanitizer.cpp
++++ b/dom/base/nsTreeSanitizer.cpp
+@@ -1423,18 +1423,18 @@ nsTreeSanitizer::SanitizeChildren(nsINod
+ mAllowStyles,
+ false);
+ }
+ node = node->GetNextNonChildNode(aRoot);
+ continue;
+ }
+ if (MustFlatten(ns, localName)) {
+ RemoveAllAttributes(node);
+- nsIContent* next = node->GetNextNode(aRoot);
+- nsIContent* parent = node->GetParent();
++ nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
++ nsCOMPtr<nsIContent> parent = node->GetParent();
+ nsCOMPtr<nsIContent> child; // Must keep the child alive during move
+ ErrorResult rv;
+ while ((child = node->GetFirstChild())) {
+ parent->InsertBefore(*child, node, rv);
+ if (rv.Failed()) {
+ break;
+ }
+ }
+diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp
+--- a/dom/html/HTMLSelectElement.cpp
++++ b/dom/html/HTMLSelectElement.cpp
+@@ -624,17 +624,17 @@ HTMLSelectElement::Add(nsGenericHTMLElem
+ {
+ if (!aBefore) {
+ Element::AppendChild(aElement, aError);
+ return;
+ }
+
+ // Just in case we're not the parent, get the parent of the reference
+ // element
+- nsINode* parent = aBefore->Element::GetParentNode();
++ nsCOMPtr<nsINode> parent = aBefore->Element::GetParentNode();
+ if (!parent || !nsContentUtils::ContentIsDescendantOf(parent, this)) {
+ // NOT_FOUND_ERR: Raised if before is not a descendant of the SELECT
+ // element.
+ aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
+ return;
+ }
+
+ // If the before parameter is not null, we are equivalent to the
+diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp
+--- a/dom/html/HTMLTableElement.cpp
++++ b/dom/html/HTMLTableElement.cpp
+@@ -516,18 +516,18 @@ HTMLTableElement::InsertRow(int32_t aInd
+ if (rowCount > 0) {
+ if (refIndex == rowCount || aIndex == -1) {
+ // we set refIndex to the last row so we can get the last row's
+ // parent we then do an AppendChild below if (rowCount<aIndex)
+
+ refIndex = rowCount - 1;
+ }
+
+- Element* refRow = rows->Item(refIndex);
+- nsINode* parent = refRow->GetParentNode();
++ RefPtr<Element> refRow = rows->Item(refIndex);
++ nsCOMPtr<nsINode> parent = refRow->GetParentNode();
+
+ // create the row
+ nsRefPtr<mozilla::dom::NodeInfo> nodeInfo;
+ nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::tr,
+ getter_AddRefs(nodeInfo));
+
+ newRow = NS_NewHTMLTableRowElement(nodeInfo.forget());
+
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1954.patch b/gnu/packages/patches/icecat-CVE-2016-1954.patch
new file mode 100644
index 0000000000..bbb4b3217c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1954.patch
@@ -0,0 +1,32 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/a5c4c18849b4
+
+# HG changeset patch
+# User Christoph Kerschbaumer <mozilla@christophkerschbaumer.com>
+# Date 1456157874 28800
+# Node ID a5c4c18849b486ef8693e20421b69239a2cbe574
+# Parent e93aeb25e2a44df8d22f5a065b4410620e2c8730
+Bug 1243178: CSP - Skip sending reports for non http schemes (r=dveditz) a=ritu
+
+diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp
+--- a/dom/security/nsCSPContext.cpp
++++ b/dom/security/nsCSPContext.cpp
+@@ -798,16 +798,17 @@ nsCSPContext::SendReports(nsISupports* a
+ (NS_SUCCEEDED(reportURI->SchemeIs("https", &isHttpScheme)) && isHttpScheme);
+
+ if (!isHttpScheme) {
+ const char16_t* params[] = { reportURIs[r].get() };
+ CSP_LogLocalizedStr(NS_LITERAL_STRING("reportURInotHttpsOrHttp2").get(),
+ params, ArrayLength(params),
+ aSourceFile, aScriptSample, aLineNum, 0,
+ nsIScriptError::errorFlag, "CSP", mInnerWindowID);
++ continue;
+ }
+
+ // make sure this is an anonymous request (no cookies) so in case the
+ // policy URI is injected, it can't be abused for CSRF.
+ nsLoadFlags flags;
+ rv = reportChannel->GetLoadFlags(&flags);
+ NS_ENSURE_SUCCESS(rv, rv);
+ flags |= nsIRequest::LOAD_ANONYMOUS;
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1960.patch b/gnu/packages/patches/icecat-CVE-2016-1960.patch
new file mode 100644
index 0000000000..6c5c885e8b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1960.patch
@@ -0,0 +1,55 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/185b233ea03f
+
+# HG changeset patch
+# User Henri Sivonen <hsivonen@hsivonen.fi>
+# Date 1455100746 -7200
+# Node ID 185b233ea03f3811404e3979b65ec86b29d13555
+# Parent 271e3a5a53d96871141e89271f611033b512e3e4
+Bug 1246014. r=wchen. a=sylvestre
+
+diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java
+--- a/parser/html/javasrc/TreeBuilder.java
++++ b/parser/html/javasrc/TreeBuilder.java
+@@ -4437,17 +4437,17 @@ public abstract class TreeBuilder<T> imp
+ return TreeBuilder.NOT_FOUND_ON_STACK;
+ }
+
+ private void clearStackBackTo(int eltPos) throws SAXException {
+ int eltGroup = stack[eltPos].getGroup();
+ while (currentPtr > eltPos) { // > not >= intentional
+ if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml"
+ && stack[currentPtr].getGroup() == TEMPLATE
+- && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltGroup == HTML)) {
++ && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltPos == 0)) {
+ return;
+ }
+ pop();
+ }
+ }
+
+ private void resetTheInsertionMode() {
+ StackNode<T> node;
+diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp
+--- a/parser/html/nsHtml5TreeBuilder.cpp
++++ b/parser/html/nsHtml5TreeBuilder.cpp
+@@ -3301,17 +3301,17 @@ nsHtml5TreeBuilder::findLastInTableScope
+ return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
+ }
+
+ void
+ nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos)
+ {
+ int32_t eltGroup = stack[eltPos]->getGroup();
+ while (currentPtr > eltPos) {
+- if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE && (eltGroup == NS_HTML5TREE_BUILDER_TABLE || eltGroup == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || eltGroup == NS_HTML5TREE_BUILDER_TR || eltGroup == NS_HTML5TREE_BUILDER_HTML)) {
++ if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE && (eltGroup == NS_HTML5TREE_BUILDER_TABLE || eltGroup == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || eltGroup == NS_HTML5TREE_BUILDER_TR || !eltPos)) {
+ return;
+ }
+ pop();
+ }
+ }
+
+ void
+ nsHtml5TreeBuilder::resetTheInsertionMode()
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1961.patch b/gnu/packages/patches/icecat-CVE-2016-1961.patch
new file mode 100644
index 0000000000..10162be24b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1961.patch
@@ -0,0 +1,33 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/e93aeb25e2a4
+
+# HG changeset patch
+# User Andrew McCreight <continuation@gmail.com>
+# Date 1455891967 28800
+# Node ID e93aeb25e2a44df8d22f5a065b4410620e2c8730
+# Parent 221de852fda32714a9e484774ceafafb450ea73c
+Bug 1249377 - Hold a strong reference to |root| in nsHTMLDocument::SetBody. r=bz, a=sylvestre
+
+diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
+--- a/dom/html/nsHTMLDocument.cpp
++++ b/dom/html/nsHTMLDocument.cpp
+@@ -1044,17 +1044,17 @@ nsHTMLDocument::SetBody(nsIDOMHTMLElemen
+ ErrorResult rv;
+ SetBody(static_cast<nsGenericHTMLElement*>(newBody.get()), rv);
+ return rv.ErrorCode();
+ }
+
+ void
+ nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
+ {
+- Element* root = GetRootElement();
++ nsCOMPtr<Element> root = GetRootElement();
+
+ // The body element must be either a body tag or a frameset tag. And we must
+ // have a html root tag, otherwise GetBody will not return the newly set
+ // body.
+ if (!newBody || !(newBody->Tag() == nsGkAtoms::body ||
+ newBody->Tag() == nsGkAtoms::frameset) ||
+ !root || !root->IsHTML() ||
+ root->Tag() != nsGkAtoms::html) {
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1962.patch b/gnu/packages/patches/icecat-CVE-2016-1962.patch
new file mode 100644
index 0000000000..7eb4e072a1
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1962.patch
@@ -0,0 +1,107 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/221de852fda3
+
+# HG changeset patch
+# User Randell Jesup <rjesup@jesup.org>
+# Date 1455862087 18000
+# Node ID 221de852fda32714a9e484774ceafafb450ea73c
+# Parent b03db72e32f6e3acdc9f8705371cb222d7e6c456
+Bug 1240760: Update DataChannel::Close() r=mcmanus, a=ritu
+
+MozReview-Commit-ID: 7nN9h3M3O8w
+
+diff --git a/netwerk/sctp/datachannel/DataChannel.cpp b/netwerk/sctp/datachannel/DataChannel.cpp
+--- a/netwerk/sctp/datachannel/DataChannel.cpp
++++ b/netwerk/sctp/datachannel/DataChannel.cpp
+@@ -1771,17 +1771,17 @@ DataChannelConnection::HandleStreamReset
+ }
+ NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
+ DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
+ channel));
+ mStreams[channel->mStream] = nullptr;
+
+ LOG(("Disconnected DataChannel %p from connection %p",
+ (void *) channel.get(), (void *) channel->mConnection.get()));
+- channel->Destroy();
++ channel->DestroyLocked();
+ // At this point when we leave here, the object is a zombie held alive only by the DOM object
+ } else {
+ LOG(("Can't find incoming channel %d",i));
+ }
+ }
+ }
+ }
+
+@@ -2498,17 +2498,17 @@ DataChannelConnection::CloseInt(DataChan
+ mStreams[channel->mStream] = nullptr;
+ } else {
+ SendOutgoingStreamReset();
+ }
+ }
+ aChannel->mState = CLOSING;
+ if (mState == CLOSED) {
+ // we're not going to hang around waiting
+- channel->Destroy();
++ channel->DestroyLocked();
+ }
+ // At this point when we leave here, the object is a zombie held alive only by the DOM object
+ }
+
+ void DataChannelConnection::CloseAll()
+ {
+ LOG(("Closing all channels (connection %p)", (void*) this));
+ // Don't need to lock here
+@@ -2552,23 +2552,25 @@ DataChannel::~DataChannel()
+ // wrong, nothing bad happens. A worst it's a leak.
+ NS_ASSERTION(mState == CLOSED || mState == CLOSING, "unexpected state in ~DataChannel");
+ }
+
+ void
+ DataChannel::Close()
+ {
+ ENSURE_DATACONNECTION;
++ RefPtr<DataChannelConnection> connection(mConnection);
+ mConnection->Close(this);
+ }
+
+ // Used when disconnecting from the DataChannelConnection
+ void
+-DataChannel::Destroy()
++DataChannel::DestroyLocked()
+ {
++ mConnection->mLock.AssertCurrentThreadOwns();
+ ENSURE_DATACONNECTION;
+
+ LOG(("Destroying Data channel %u", mStream));
+ MOZ_ASSERT_IF(mStream != INVALID_STREAM,
+ !mConnection->FindChannelByStream(mStream));
+ mStream = INVALID_STREAM;
+ mState = CLOSED;
+ mConnection = nullptr;
+diff --git a/netwerk/sctp/datachannel/DataChannel.h b/netwerk/sctp/datachannel/DataChannel.h
+--- a/netwerk/sctp/datachannel/DataChannel.h
++++ b/netwerk/sctp/datachannel/DataChannel.h
+@@ -331,19 +331,20 @@ public:
+ {
+ NS_ASSERTION(mConnection,"NULL connection");
+ }
+
+ private:
+ ~DataChannel();
+
+ public:
+- void Destroy(); // when we disconnect from the connection after stream RESET
++ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
+
+- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
++ // when we disconnect from the connection after stream RESET
++ void DestroyLocked();
+
+ // Close this DataChannel. Can be called multiple times. MUST be called
+ // before destroying the DataChannel (state must be CLOSED or CLOSING).
+ void Close();
+
+ // Set the listener (especially for channels created from the other side)
+ void SetListener(DataChannelListener *aListener, nsISupports *aContext);
+
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1964.patch b/gnu/packages/patches/icecat-CVE-2016-1964.patch
new file mode 100644
index 0000000000..e53fc749b5
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1964.patch
@@ -0,0 +1,54 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/a653013e7b50
+
+# HG changeset patch
+# User Peter Van der Beken <peterv@propagandism.org>
+# Date 1454340035 -3600
+# Node ID a653013e7b503912a32621e8da64a37171316588
+# Parent 0d0d7e8292f7ecf5f1149d528c0524f04447c4ad
+Bug 1243335 - report bad QName. r=sicking, a=sylvestre
+
+diff --git a/dom/xslt/xslt/txInstructions.cpp b/dom/xslt/xslt/txInstructions.cpp
+--- a/dom/xslt/xslt/txInstructions.cpp
++++ b/dom/xslt/xslt/txInstructions.cpp
+@@ -93,16 +93,19 @@ txAttribute::txAttribute(nsAutoPtr<Expr>
+ txNamespaceMap* aMappings)
+ : mName(Move(aName)), mNamespace(Move(aNamespace)), mMappings(aMappings)
+ {
+ }
+
+ nsresult
+ txAttribute::execute(txExecutionState& aEs)
+ {
++ nsAutoPtr<txTextHandler> handler(
++ static_cast<txTextHandler*>(aEs.popResultHandler()));
++
+ nsAutoString name;
+ nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ const char16_t* colon;
+ if (!XMLUtils::isValidQName(name, &colon) ||
+ TX_StringEqualsAtom(name, nsGkAtoms::xmlns)) {
+ return NS_OK;
+@@ -125,19 +128,16 @@ txAttribute::execute(txExecutionState& a
+ if (!nspace.IsEmpty()) {
+ nsId = txNamespaceManager::getNamespaceID(nspace);
+ }
+ }
+ else if (colon) {
+ nsId = mMappings->lookupNamespace(prefix);
+ }
+
+- nsAutoPtr<txTextHandler> handler(
+- static_cast<txTextHandler*>(aEs.popResultHandler()));
+-
+ // add attribute if everything was ok
+ return nsId != kNameSpaceID_Unknown ?
+ aEs.mResultHandler->attribute(prefix, Substring(name, lnameStart),
+ nsId, handler->mValue) :
+ NS_OK;
+ }
+
+ txCallTemplate::txCallTemplate(const txExpandedName& aName)
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1965.patch b/gnu/packages/patches/icecat-CVE-2016-1965.patch
new file mode 100644
index 0000000000..8a37d4975c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1965.patch
@@ -0,0 +1,44 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/b4467681abd6
+
+# HG changeset patch
+# User Gijs Kruitbosch <gijskruitbosch@gmail.com>
+# Date 1455276061 0
+# Node ID b4467681abd676cd5575cbdf922927f8f54d2ad9
+# Parent 8c1d40e45a72c6432e879137a0afa519dc6c9841
+Bug 1245264 - r=bz, r=ritu
+
+MozReview-Commit-ID: I0sVdritpD3
+
+diff --git a/dom/base/nsLocation.cpp b/dom/base/nsLocation.cpp
+--- a/dom/base/nsLocation.cpp
++++ b/dom/base/nsLocation.cpp
+@@ -735,16 +735,27 @@ nsLocation::SetProtocol(const nsAString&
+ return rv;
+ }
+
+ rv = uri->SetScheme(NS_ConvertUTF16toUTF8(aProtocol));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
++ nsAutoCString newSpec;
++ rv = uri->GetSpec(newSpec);
++ if (NS_FAILED(rv)) {
++ return rv;
++ }
++ // We may want a new URI class for the new URI, so recreate it:
++ rv = NS_NewURI(getter_AddRefs(uri), newSpec);
++ if (NS_FAILED(rv)) {
++ return rv;
++ }
++
+ return SetURI(uri);
+ }
+
+ void
+ nsLocation::GetUsername(nsAString& aUsername, ErrorResult& aError)
+ {
+ if (!CallerSubsumes()) {
+ aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1966.patch b/gnu/packages/patches/icecat-CVE-2016-1966.patch
new file mode 100644
index 0000000000..6bf5f9f95e
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1966.patch
@@ -0,0 +1,36 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/291c2f31c48c
+
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1454650565 -39600
+# Node ID 291c2f31c48c7e96b1884b55273355970fa0fc30
+# Parent 11e6614756551cfd7291e73eefb90c52873a8480
+Bug 1246054 - Fix an erroneous nsNPObjWrapper assertion. r=froydnj. a=ritu
+
+diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp
+--- a/dom/plugins/base/nsJSNPRuntime.cpp
++++ b/dom/plugins/base/nsJSNPRuntime.cpp
+@@ -1915,18 +1915,19 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
+ // No existing JSObject, create one.
+
+ JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, js::Jsvalify(&sNPObjectJSWrapperClass)));
+
+ if (generation != sNPObjWrappers.Generation()) {
+ // Reload entry if the JS_NewObject call caused a GC and reallocated
+ // the table (see bug 445229). This is guaranteed to succeed.
+
+- NS_ASSERTION(PL_DHashTableSearch(&sNPObjWrappers, npobj),
+- "Hashtable didn't find what we just added?");
++ entry = static_cast<NPObjWrapperHashEntry*>
++ (PL_DHashTableSearch(&sNPObjWrappers, npobj));
++ NS_ASSERTION(entry, "Hashtable didn't find what we just added?");
+ }
+
+ if (!obj) {
+ // OOM? Remove the stale entry from the hash.
+
+ PL_DHashTableRawRemove(&sNPObjWrappers, entry);
+
+ return nullptr;
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-1974.patch b/gnu/packages/patches/icecat-CVE-2016-1974.patch
new file mode 100644
index 0000000000..70fc23b8f3
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-1974.patch
@@ -0,0 +1,530 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/271e3a5a53d9
+
+# HG changeset patch
+# User Henri Sivonen <hsivonen@hsivonen.fi>
+# Date 1455014759 -7200
+# Node ID 271e3a5a53d96871141e89271f611033b512e3e4
+# Parent 9719b71d72dd2a3c5ee12ace156af2a63d9595ac
+Bug 1228103. r=smaug. a=sylvestre
+
+diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp
+--- a/parser/htmlparser/nsExpatDriver.cpp
++++ b/parser/htmlparser/nsExpatDriver.cpp
+@@ -1127,22 +1127,28 @@ nsExpatDriver::ConsumeToken(nsScanner& a
+ XML_Size lastLineLength = XML_GetCurrentColumnNumber(mExpatParser);
+
+ if (lastLineLength <= consumed) {
+ // The length of the last line was less than what expat consumed, so
+ // there was at least one line break in the consumed data. Store the
+ // last line until the point where we stopped parsing.
+ nsScannerIterator startLastLine = currentExpatPosition;
+ startLastLine.advance(-((ptrdiff_t)lastLineLength));
+- CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine);
++ if (!CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine)) {
++ return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
++ }
+ }
+ else {
+ // There was no line break in the consumed data, append the consumed
+ // data.
+- AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine);
++ if (!AppendUnicodeTo(oldExpatPosition,
++ currentExpatPosition,
++ mLastLine)) {
++ return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
++ }
+ }
+ }
+
+ mExpatBuffered += length - consumed;
+
+ if (BlockedOrInterrupted()) {
+ PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
+ ("Blocked or interrupted parser (probably for loading linked "
+diff --git a/parser/htmlparser/nsParser.cpp b/parser/htmlparser/nsParser.cpp
+--- a/parser/htmlparser/nsParser.cpp
++++ b/parser/htmlparser/nsParser.cpp
+@@ -1508,17 +1508,19 @@ nsParser::ResumeParse(bool allowIteratio
+ DidBuildModel(mStreamStatus);
+ return NS_OK;
+ }
+ } else {
+ CParserContext* theContext = PopContext();
+ if (theContext) {
+ theIterationIsOk = allowIteration && theContextIsStringBased;
+ if (theContext->mCopyUnused) {
+- theContext->mScanner->CopyUnusedData(mUnusedInput);
++ if (!theContext->mScanner->CopyUnusedData(mUnusedInput)) {
++ mInternalState = NS_ERROR_OUT_OF_MEMORY;
++ }
+ }
+
+ delete theContext;
+ }
+
+ result = mInternalState;
+ aIsFinalChunk = mParserContext &&
+ mParserContext->mStreamListenerState == eOnStop;
+diff --git a/parser/htmlparser/nsScanner.cpp b/parser/htmlparser/nsScanner.cpp
+--- a/parser/htmlparser/nsScanner.cpp
++++ b/parser/htmlparser/nsScanner.cpp
+@@ -379,17 +379,19 @@ nsresult nsScanner::Peek(nsAString& aStr
+ if (mCountRemaining < uint32_t(aNumChars + aOffset)) {
+ end = mEndPosition;
+ }
+ else {
+ end = start;
+ end.advance(aNumChars);
+ }
+
+- CopyUnicodeTo(start, end, aStr);
++ if (!CopyUnicodeTo(start, end, aStr)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+
+ return NS_OK;
+ }
+
+
+ /**
+ * Skip whitespace on scanner input stream
+ *
+@@ -542,17 +544,19 @@ nsresult nsScanner::ReadTagIdentifier(ns
+
+ if (!found) {
+ ++current;
+ }
+ }
+
+ // Don't bother appending nothing.
+ if (current != mCurrentPosition) {
+- AppendUnicodeTo(mCurrentPosition, current, aString);
++ if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ }
+
+ SetPosition(current);
+ if (current == end) {
+ result = kEOF;
+ }
+
+ //DoErrTest(aString);
+@@ -597,26 +601,30 @@ nsresult nsScanner::ReadEntityIdentifier
+ default:
+ found = ('a'<=theChar && theChar<='z') ||
+ ('A'<=theChar && theChar<='Z') ||
+ ('0'<=theChar && theChar<='9');
+ break;
+ }
+
+ if(!found) {
+- AppendUnicodeTo(mCurrentPosition, current, aString);
++ if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ break;
+ }
+ }
+ ++current;
+ }
+
+ SetPosition(current);
+ if (current == end) {
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ return kEOF;
+ }
+
+ //DoErrTest(aString);
+
+ return result;
+ }
+
+@@ -646,26 +654,30 @@ nsresult nsScanner::ReadNumber(nsString&
+ while(current != end) {
+ theChar=*current;
+ if(theChar) {
+ done = (theChar < '0' || theChar > '9') &&
+ ((aBase == 16)? (theChar < 'A' || theChar > 'F') &&
+ (theChar < 'a' || theChar > 'f')
+ :true);
+ if(done) {
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ break;
+ }
+ }
+ ++current;
+ }
+
+ SetPosition(current);
+ if (current == end) {
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ return kEOF;
+ }
+
+ //DoErrTest(aString);
+
+ return result;
+ }
+
+@@ -712,37 +724,43 @@ nsresult nsScanner::ReadWhitespace(nsSca
+ char16_t thePrevChar = theChar;
+ theChar = (++current != end) ? *current : '\0';
+ if ((thePrevChar == '\r' && theChar == '\n') ||
+ (thePrevChar == '\n' && theChar == '\r')) {
+ theChar = (++current != end) ? *current : '\0'; // CRLF == LFCR => LF
+ haveCR = true;
+ } else if (thePrevChar == '\r') {
+ // Lone CR becomes CRLF; callers should know to remove extra CRs
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ aString.writable().Append(char16_t('\n'));
+ origin = current;
+ haveCR = true;
+ }
+ }
+ break;
+ case ' ' :
+ case '\t':
+ theChar = (++current != end) ? *current : '\0';
+ break;
+ default:
+ done = true;
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ break;
+ }
+ }
+
+ SetPosition(current);
+ if (current == end) {
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ result = kEOF;
+ }
+
+ aHaveCR = haveCR;
+ return result;
+ }
+
+ //XXXbz callers of this have to manage their lone '\r' themselves if they want
+@@ -846,34 +864,38 @@ nsresult nsScanner::ReadUntil(nsAString&
+ if(!(theChar & aEndCondition.mFilter)) {
+ // They were. Do a thorough check.
+
+ setcurrent = setstart;
+ while (*setcurrent) {
+ if (*setcurrent == theChar) {
+ if(addTerminal)
+ ++current;
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ SetPosition(current);
+
+ //DoErrTest(aString);
+
+ return NS_OK;
+ }
+ ++setcurrent;
+ }
+ }
+
+ ++current;
+ }
+
+ // If we are here, we didn't find any terminator in the string and
+ // current = mEndPosition
+ SetPosition(current);
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ return kEOF;
+ }
+
+ nsresult nsScanner::ReadUntil(nsScannerSharedSubstring& aString,
+ const nsReadEndCondition& aEndCondition,
+ bool addTerminal)
+ {
+ if (!mSlidingBuffer) {
+@@ -906,34 +928,38 @@ nsresult nsScanner::ReadUntil(nsScannerS
+ if(!(theChar & aEndCondition.mFilter)) {
+ // They were. Do a thorough check.
+
+ setcurrent = setstart;
+ while (*setcurrent) {
+ if (*setcurrent == theChar) {
+ if(addTerminal)
+ ++current;
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ SetPosition(current);
+
+ //DoErrTest(aString);
+
+ return NS_OK;
+ }
+ ++setcurrent;
+ }
+ }
+
+ ++current;
+ }
+
+ // If we are here, we didn't find any terminator in the string and
+ // current = mEndPosition
+ SetPosition(current);
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ return kEOF;
+ }
+
+ nsresult nsScanner::ReadUntil(nsScannerIterator& aStart,
+ nsScannerIterator& aEnd,
+ const nsReadEndCondition &aEndCondition,
+ bool addTerminal)
+ {
+@@ -1025,26 +1051,30 @@ nsresult nsScanner::ReadUntil(nsAString&
+ if (theChar == '\0') {
+ ReplaceCharacter(current, sInvalid);
+ theChar = sInvalid;
+ }
+
+ if (aTerminalChar == theChar) {
+ if(addTerminal)
+ ++current;
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ SetPosition(current);
+ return NS_OK;
+ }
+ ++current;
+ }
+
+ // If we are here, we didn't find any terminator in the string and
+ // current = mEndPosition
+- AppendUnicodeTo(origin, current, aString);
++ if (!AppendUnicodeTo(origin, current, aString)) {
++ return NS_ERROR_OUT_OF_MEMORY;
++ }
+ SetPosition(current);
+ return kEOF;
+
+ }
+
+ void nsScanner::BindSubstring(nsScannerSubstring& aSubstring, const nsScannerIterator& aStart, const nsScannerIterator& aEnd)
+ {
+ aSubstring.Rebind(*mSlidingBuffer, aStart, aEnd);
+@@ -1142,29 +1172,29 @@ bool nsScanner::AppendToBuffer(nsScanner
+ }
+
+ /**
+ * call this to copy bytes out of the scanner that have not yet been consumed
+ * by the tokenization process.
+ *
+ * @update gess 5/12/98
+ * @param aCopyBuffer is where the scanner buffer will be copied to
+- * @return nada
++ * @return true if OK or false on OOM
+ */
+-void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
++bool nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
+ if (!mSlidingBuffer) {
+ aCopyBuffer.Truncate();
+- return;
++ return true;
+ }
+
+ nsScannerIterator start, end;
+ start = mCurrentPosition;
+ end = mEndPosition;
+
+- CopyUnicodeTo(start, end, aCopyBuffer);
++ return CopyUnicodeTo(start, end, aCopyBuffer);
+ }
+
+ /**
+ * Retrieve the name of the file that the scanner is reading from.
+ * In some cases, it's just a given name, because the scanner isn't
+ * really reading from a file.
+ *
+ * @update gess 5/12/98
+diff --git a/parser/htmlparser/nsScanner.h b/parser/htmlparser/nsScanner.h
+--- a/parser/htmlparser/nsScanner.h
++++ b/parser/htmlparser/nsScanner.h
+@@ -204,19 +204,19 @@ class nsScanner {
+ nsIRequest *aRequest);
+
+ /**
+ * Call this to copy bytes out of the scanner that have not yet been consumed
+ * by the tokenization process.
+ *
+ * @update gess 5/12/98
+ * @param aCopyBuffer is where the scanner buffer will be copied to
+- * @return nada
++ * @return true if OK or false on OOM
+ */
+- void CopyUnusedData(nsString& aCopyBuffer);
++ bool CopyUnusedData(nsString& aCopyBuffer);
+
+ /**
+ * Retrieve the name of the file that the scanner is reading from.
+ * In some cases, it's just a given name, because the scanner isn't
+ * really reading from a file.
+ *
+ * @update gess 5/12/98
+ * @return
+diff --git a/parser/htmlparser/nsScannerString.cpp b/parser/htmlparser/nsScannerString.cpp
+--- a/parser/htmlparser/nsScannerString.cpp
++++ b/parser/htmlparser/nsScannerString.cpp
+@@ -461,61 +461,63 @@ copy_multifragment_string( nsScannerIter
+ sink_traits::write(result, source_traits::read(first), distance);
+ NS_ASSERTION(distance > 0, "|copy_multifragment_string| will never terminate");
+ source_traits::advance(first, distance);
+ }
+
+ return result;
+ }
+
+-void
++bool
+ CopyUnicodeTo( const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd,
+ nsAString& aDest )
+ {
+ nsAString::iterator writer;
+ if (!aDest.SetLength(Distance(aSrcStart, aSrcEnd), mozilla::fallible)) {
+ aDest.Truncate();
+- return; // out of memory
++ return false; // out of memory
+ }
+ aDest.BeginWriting(writer);
+ nsScannerIterator fromBegin(aSrcStart);
+
+ copy_multifragment_string(fromBegin, aSrcEnd, writer);
++ return true;
+ }
+
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd,
+ nsScannerSharedSubstring& aDest )
+ {
+ // Check whether we can just create a dependent string.
+ if (aDest.str().IsEmpty()) {
+ // We can just make |aDest| point to the buffer.
+ // This will take care of copying if the buffer spans fragments.
+ aDest.Rebind(aSrcStart, aSrcEnd);
+- } else {
+- // The dest string is not empty, so it can't be a dependent substring.
+- AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
++ return true;
+ }
++ // The dest string is not empty, so it can't be a dependent substring.
++ return AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
+ }
+
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd,
+ nsAString& aDest )
+ {
+ nsAString::iterator writer;
+ uint32_t oldLength = aDest.Length();
+ if (!aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd), mozilla::fallible))
+- return; // out of memory
++ return false; // out of memory
+ aDest.BeginWriting(writer).advance(oldLength);
+ nsScannerIterator fromBegin(aSrcStart);
+
+ copy_multifragment_string(fromBegin, aSrcEnd, writer);
++ return true;
+ }
+
+ bool
+ FindCharInReadable( char16_t aChar,
+ nsScannerIterator& aSearchStart,
+ const nsScannerIterator& aSearchEnd )
+ {
+ while ( aSearchStart != aSearchEnd )
+diff --git a/parser/htmlparser/nsScannerString.h b/parser/htmlparser/nsScannerString.h
+--- a/parser/htmlparser/nsScannerString.h
++++ b/parser/htmlparser/nsScannerString.h
+@@ -539,43 +539,43 @@ nsScannerBufferList::Position::operator=
+ inline
+ size_t
+ Distance( const nsScannerIterator& aStart, const nsScannerIterator& aEnd )
+ {
+ typedef nsScannerBufferList::Position Position;
+ return Position::Distance(Position(aStart), Position(aEnd));
+ }
+
+-void
++bool
+ CopyUnicodeTo( const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd,
+ nsAString& aDest );
+
+ inline
+-void
++bool
+ CopyUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
+ {
+ nsScannerIterator begin, end;
+- CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
++ return CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
+ }
+
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd,
+ nsAString& aDest );
+
+ inline
+-void
++bool
+ AppendUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
+ {
+ nsScannerIterator begin, end;
+- AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
++ return AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
+ }
+
+-void
++bool
+ AppendUnicodeTo( const nsScannerIterator& aSrcStart,
+ const nsScannerIterator& aSrcEnd,
+ nsScannerSharedSubstring& aDest );
+
+ bool
+ FindCharInReadable( char16_t aChar,
+ nsScannerIterator& aStart,
+ const nsScannerIterator& aEnd );
+
diff --git a/gnu/packages/patches/icecat-bug-1248851.patch b/gnu/packages/patches/icecat-bug-1248851.patch
new file mode 100644
index 0000000000..ea4d6831b5
--- /dev/null
+++ b/gnu/packages/patches/icecat-bug-1248851.patch
@@ -0,0 +1,37 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/8c1d40e45a72
+
+# HG changeset patch
+# User Xidorn Quan <quanxunzhen@gmail.com>
+# Date 1456199544 -28800
+# Node ID 8c1d40e45a72c6432e879137a0afa519dc6c9841
+# Parent 1dd0ca8e70bd77b6fd93f36cc4e9c2cebfe8ba0a
+Bug 1248851 - r=sicking, a=ritu
+
+diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
+--- a/dom/indexedDB/ActorsParent.cpp
++++ b/dom/indexedDB/ActorsParent.cpp
+@@ -14823,22 +14823,19 @@ ObjectStoreAddOrPutRequestOp::DoDatabase
+ }
+
+ snappy::RawCompress(uncompressed, uncompressedLength, compressed,
+ &compressedLength);
+
+ uint8_t* dataBuffer = reinterpret_cast<uint8_t*>(compressed);
+ size_t dataBufferLength = compressedLength;
+
+- // If this call succeeds, | compressed | is now owned by the statement, and
+- // we are no longer responsible for it.
+ rv = stmt->BindAdoptedBlobByName(NS_LITERAL_CSTRING("data"), dataBuffer,
+ dataBufferLength);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+- moz_free(compressed);
+ return rv;
+ }
+ }
+
+ nsCOMPtr<nsIFile> fileDirectory;
+ nsCOMPtr<nsIFile> journalDirectory;
+
+ if (mFileManager) {
+
diff --git a/gnu/packages/patches/icecat-update-graphite2-pt2.patch b/gnu/packages/patches/icecat-update-graphite2-pt2.patch
new file mode 100644
index 0000000000..8acde75d6c
--- /dev/null
+++ b/gnu/packages/patches/icecat-update-graphite2-pt2.patch
@@ -0,0 +1,861 @@
+Copied from upstream:
+https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/ec9cff7bb543
+
+# HG changeset patch
+# User Jonathan Kew <jkew@mozilla.com>
+# Date 1456760339 0
+# Node ID ec9cff7bb5439b2b4c1249ff9376d07a80172c27
+# Parent 6f4d5130238790fa5810c76ffeb9eccc65efa8c9
+Bug 1248876 - Update graphite2 to upstream release 1.3.6. r=jrmuizel a=sledru
+
+diff --git a/gfx/graphite2/README.mozilla b/gfx/graphite2/README.mozilla
+--- a/gfx/graphite2/README.mozilla
++++ b/gfx/graphite2/README.mozilla
+@@ -1,7 +1,3 @@
+-This directory contains the Graphite2 library release 1.3.5 from
+-https://github.com/silnrsi/graphite/releases/download/1.3.5/graphite2-minimal-1.3.5.tgz
++This directory contains the Graphite2 library release 1.3.6 from
++https://github.com/silnrsi/graphite/releases/download/1.3.6/graphite-minimal-1.3.6.tgz
+ See gfx/graphite2/moz-gr-update.sh for update procedure.
+-
+-Also includes two post-1.3.5 fixes:
+-a8b3ac2aed0eb132cd80efe7de88f8153e73c829
+-e569e28d83491fedb31b9220493f3c07f6ec6d80
+diff --git a/gfx/graphite2/include/graphite2/Font.h b/gfx/graphite2/include/graphite2/Font.h
+--- a/gfx/graphite2/include/graphite2/Font.h
++++ b/gfx/graphite2/include/graphite2/Font.h
+@@ -25,17 +25,17 @@
+ either version 2 of the License or (at your option) any later version.
+ */
+ #pragma once
+
+ #include "graphite2/Types.h"
+
+ #define GR2_VERSION_MAJOR 1
+ #define GR2_VERSION_MINOR 3
+-#define GR2_VERSION_BUGFIX 5
++#define GR2_VERSION_BUGFIX 6
+
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+ typedef struct gr_face gr_face;
+ typedef struct gr_font gr_font;
+diff --git a/gfx/graphite2/moz-gr-update.sh b/gfx/graphite2/moz-gr-update.sh
+--- a/gfx/graphite2/moz-gr-update.sh
++++ b/gfx/graphite2/moz-gr-update.sh
+@@ -14,17 +14,17 @@
+ RELEASE=$1
+
+ if [ "x$RELEASE" == "x" ]
+ then
+ echo "Must provide the version number to be used."
+ exit 1
+ fi
+
+-TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite2-minimal-$RELEASE.tgz"
++TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite-minimal-$RELEASE.tgz"
+
+ foo=`basename $0`
+ TMPFILE=`mktemp -t ${foo}` || exit 1
+
+ curl -L "$TARBALL" -o "$TMPFILE"
+ tar -x -z -C gfx/graphite2/ --strip-components 1 -f "$TMPFILE" || exit 1
+ rm "$TMPFILE"
+
+diff --git a/gfx/graphite2/src/CmapCache.cpp b/gfx/graphite2/src/CmapCache.cpp
+--- a/gfx/graphite2/src/CmapCache.cpp
++++ b/gfx/graphite2/src/CmapCache.cpp
+@@ -33,43 +33,43 @@ of the License or (at your option) any l
+
+
+ using namespace graphite2;
+
+ const void * bmp_subtable(const Face::Table & cmap)
+ {
+ const void * stbl;
+ if (!cmap.size()) return 0;
+- if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap.size())
+- || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap.size())
+- || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap.size())
+- || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap.size())
+- || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap.size()))
++ if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap + cmap.size())
++ || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap + cmap.size())
++ || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap + cmap.size())
++ || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap + cmap.size())
++ || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap + cmap.size()))
+ return stbl;
+ return 0;
+ }
+
+ const void * smp_subtable(const Face::Table & cmap)
+ {
+ const void * stbl;
+ if (!cmap.size()) return 0;
+- if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap.size())
+- || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap.size()))
++ if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap + cmap.size())
++ || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap + cmap.size()))
+ return stbl;
+ return 0;
+ }
+
+ template <unsigned int (*NextCodePoint)(const void *, unsigned int, int *),
+ uint16 (*LookupCodePoint)(const void *, unsigned int, int)>
+ bool cache_subtable(uint16 * blocks[], const void * cst, const unsigned int limit)
+ {
+ int rangeKey = 0;
+ uint32 codePoint = NextCodePoint(cst, 0, &rangeKey),
+ prevCodePoint = 0;
+- while (codePoint != limit)
++ while (codePoint < limit)
+ {
+ unsigned int block = codePoint >> 8;
+ if (!blocks[block])
+ {
+ blocks[block] = grzeroalloc<uint16>(0x100);
+ if (!blocks[block])
+ return false;
+ }
+diff --git a/gfx/graphite2/src/Code.cpp b/gfx/graphite2/src/Code.cpp
+--- a/gfx/graphite2/src/Code.cpp
++++ b/gfx/graphite2/src/Code.cpp
+@@ -79,18 +79,19 @@ struct context
+
+
+ class Machine::Code::decoder
+ {
+ public:
+ struct limits;
+ struct analysis
+ {
++ static const int NUMCONTEXTS = 256;
+ uint8 slotref;
+- context contexts[256];
++ context contexts[NUMCONTEXTS];
+ byte max_ref;
+
+ analysis() : slotref(0), max_ref(0) {};
+ void set_ref(int index, bool incinsert=false) throw();
+ void set_noref(int index) throw();
+ void set_changed(int index) throw();
+
+ };
+@@ -363,29 +364,33 @@ opcode Machine::Code::decoder::fetch_opc
+ break;
+ case ATTR_SET :
+ case ATTR_ADD :
+ case ATTR_SUB :
+ case ATTR_SET_SLOT :
+ if (--_stack_depth < 0)
+ failure(underfull_stack);
+ valid_upto(gr_slatMax, bc[0]);
++ if (attrCode(bc[0]) == gr_slatUserDefn) // use IATTR for user attributes
++ failure(out_of_range_data);
+ test_context();
+ break;
+ case IATTR_SET_SLOT :
+ if (--_stack_depth < 0)
+ failure(underfull_stack);
+ if (valid_upto(gr_slatMax, bc[0]))
+ valid_upto(_max.attrid[bc[0]], bc[1]);
+ test_context();
+ break;
+ case PUSH_SLOT_ATTR :
+ ++_stack_depth;
+ valid_upto(gr_slatMax, bc[0]);
+ valid_upto(_rule_length, _pre_context + int8(bc[1]));
++ if (attrCode(bc[0]) == gr_slatUserDefn) // use IATTR for user attributes
++ failure(out_of_range_data);
+ break;
+ case PUSH_GLYPH_ATTR_OBS :
+ ++_stack_depth;
+ valid_upto(_max.glyf_attrs, bc[0]);
+ valid_upto(_rule_length, _pre_context + int8(bc[1]));
+ break;
+ case PUSH_GLYPH_METRIC :
+ ++_stack_depth;
+@@ -656,24 +661,24 @@ bool Machine::Code::decoder::validate_op
+ return false;
+ }
+ return true;
+ }
+
+
+ bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) const throw()
+ {
+- const bool t = x < limit;
++ const bool t = (limit != 0) && (x < limit);
+ if (!t) failure(out_of_range_data);
+ return t;
+ }
+
+ bool Machine::Code::decoder::test_context() const throw()
+ {
+- if (_pre_context >= _rule_length)
++ if (_pre_context >= _rule_length || _analysis.slotref >= analysis::NUMCONTEXTS - 1)
+ {
+ failure(out_of_range_data);
+ return false;
+ }
+ return true;
+ }
+
+ inline
+@@ -681,34 +686,34 @@ void Machine::Code::failure(const status
+ release_buffers();
+ _status = s;
+ }
+
+
+ inline
+ void Machine::Code::decoder::analysis::set_ref(int index, bool incinsert) throw() {
+ if (incinsert && contexts[slotref].flags.inserted) --index;
+- if (index + slotref < 0) return;
++ if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
+ contexts[index + slotref].flags.referenced = true;
+ if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
+ }
+
+
+ inline
+ void Machine::Code::decoder::analysis::set_noref(int index) throw() {
+ if (contexts[slotref].flags.inserted) --index;
+- if (index + slotref < 0) return;
++ if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
+ if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
+ }
+
+
+ inline
+ void Machine::Code::decoder::analysis::set_changed(int index) throw() {
+ if (contexts[slotref].flags.inserted) --index;
+- if (index + slotref < 0) return;
++ if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
+ contexts[index + slotref].flags.changed = true;
+ if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
+ }
+
+
+ void Machine::Code::release_buffers() throw()
+ {
+ if (_own)
+diff --git a/gfx/graphite2/src/GlyphCache.cpp b/gfx/graphite2/src/GlyphCache.cpp
+--- a/gfx/graphite2/src/GlyphCache.cpp
++++ b/gfx/graphite2/src/GlyphCache.cpp
+@@ -260,17 +260,17 @@ GlyphCache::Loader::Loader(const Face &
+ _head = Face::Table();
+ return;
+ }
+
+ if (!dumb_font)
+ {
+ if ((m_pGlat = Face::Table(face, Tag::Glat, 0x00030000)) == NULL
+ || (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
+- || m_pGloc.size() < 6)
++ || m_pGloc.size() < 8)
+ {
+ _head = Face::Table();
+ return;
+ }
+ const byte * p = m_pGloc;
+ int version = be::read<uint32>(p);
+ const uint16 flags = be::read<uint16>(p);
+ _num_attrs = be::read<uint16>(p);
+diff --git a/gfx/graphite2/src/Pass.cpp b/gfx/graphite2/src/Pass.cpp
+--- a/gfx/graphite2/src/Pass.cpp
++++ b/gfx/graphite2/src/Pass.cpp
+@@ -233,17 +233,17 @@ bool Pass::readRules(const byte * rule_m
+ m_codes = new Code [m_numRules*2];
+ const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data);
+ m_progs = gralloc<byte>(prog_pool_sz);
+ byte * prog_pool_free = m_progs,
+ * prog_pool_end = m_progs + prog_pool_sz;
+ if (e.test(!(m_rules && m_codes && m_progs), E_OUTOFMEM)) return face.error(e);
+
+ Rule * r = m_rules + m_numRules - 1;
+- for (size_t n = m_numRules; n; --n, --r, ac_end = ac_begin, rc_end = rc_begin)
++ for (size_t n = m_numRules; r >= m_rules; --n, --r, ac_end = ac_begin, rc_end = rc_begin)
+ {
+ face.error_context((face.error_context() & 0xFFFF00) + EC_ARULE + ((n - 1) << 24));
+ r->preContext = *--precontext;
+ r->sort = be::peek<uint16>(--sort_key);
+ #ifndef NDEBUG
+ r->rule_idx = n - 1;
+ #endif
+ if (r->sort > 63 || r->preContext >= r->sort || r->preContext > m_maxPreCtxt || r->preContext < m_minPreCtxt)
+@@ -405,16 +405,17 @@ bool Pass::runGraphite(vm::Machine & m,
+ json::closer rules_array_closer(fsm.dbgout);
+ #endif
+
+ m.slotMap().highwater(currHigh);
+ int lc = m_iMaxLoop;
+ do
+ {
+ findNDoRule(s, m, fsm);
++ if (m.status() != Machine::finished) return false;
+ if (s && (s == m.slotMap().highwater() || m.slotMap().highpassed() || --lc == 0)) {
+ if (!lc)
+ s = m.slotMap().highwater();
+ lc = m_iMaxLoop;
+ if (s)
+ m.slotMap().highwater(s->next());
+ }
+ } while (s);
+@@ -495,17 +496,22 @@ void Pass::findNDoRule(Slot * & slot, Ma
+ {
+ assert(slot);
+
+ if (runFSM(fsm, slot))
+ {
+ // Search for the first rule which passes the constraint
+ const RuleEntry * r = fsm.rules.begin(),
+ * const re = fsm.rules.end();
+- while (r != re && !testConstraint(*r->rule, m)) ++r;
++ while (r != re && !testConstraint(*r->rule, m))
++ {
++ ++r;
++ if (m.status() != Machine::finished)
++ return;
++ }
+
+ #if !defined GRAPHITE2_NTRACING
+ if (fsm.dbgout)
+ {
+ if (fsm.rules.size() != 0)
+ {
+ *fsm.dbgout << json::item << json::object;
+ dumpRuleEventConsidered(fsm, *r);
+@@ -530,16 +536,17 @@ void Pass::findNDoRule(Slot * & slot, Ma
+ }
+ }
+ else
+ #endif
+ {
+ if (r != re)
+ {
+ const int adv = doAction(r->rule->action, slot, m);
++ if (m.status() != Machine::finished) return;
+ if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot);
+ adjustSlot(adv, slot, fsm.slots);
+ return;
+ }
+ }
+ }
+
+ slot = slot->next();
+diff --git a/gfx/graphite2/src/Segment.cpp b/gfx/graphite2/src/Segment.cpp
+--- a/gfx/graphite2/src/Segment.cpp
++++ b/gfx/graphite2/src/Segment.cpp
+@@ -205,18 +205,23 @@ Slot *Segment::newSlot()
+ void Segment::freeSlot(Slot *aSlot)
+ {
+ if (m_last == aSlot) m_last = aSlot->prev();
+ if (m_first == aSlot) m_first = aSlot->next();
+ if (aSlot->attachedTo())
+ aSlot->attachedTo()->removeChild(aSlot);
+ while (aSlot->firstChild())
+ {
+- aSlot->firstChild()->attachTo(NULL);
+- aSlot->removeChild(aSlot->firstChild());
++ if (aSlot->firstChild()->attachedTo() == aSlot)
++ {
++ aSlot->firstChild()->attachTo(NULL);
++ aSlot->removeChild(aSlot->firstChild());
++ }
++ else
++ aSlot->firstChild(NULL);
+ }
+ // reset the slot incase it is reused
+ ::new (aSlot) Slot(aSlot->userAttrs());
+ memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
+ // Update generation counter for debug
+ #if !defined GRAPHITE2_NTRACING
+ if (m_face->logger())
+ ++aSlot->userAttrs()[m_silf->numUser()];
+diff --git a/gfx/graphite2/src/Slot.cpp b/gfx/graphite2/src/Slot.cpp
+--- a/gfx/graphite2/src/Slot.cpp
++++ b/gfx/graphite2/src/Slot.cpp
+@@ -192,16 +192,18 @@ int32 Slot::clusterMetric(const Segment
+ #define SLOTGETCOLATTR(x) { SlotCollision *c = seg->collisionInfo(this); return c ? int(c-> x) : 0; }
+
+ int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
+ {
+ if (ind == gr_slatUserDefnV1)
+ {
+ ind = gr_slatUserDefn;
+ subindex = 0;
++ if (seg->numAttrs() == 0)
++ return 0;
+ }
+ else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
+ {
+ int indx = ind - gr_slatJStretch;
+ return getJustify(seg, indx / 5, indx % 5);
+ }
+
+ switch (ind)
+@@ -269,16 +271,18 @@ int Slot::getAttr(const Segment *seg, at
+ break; }
+
+ void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
+ {
+ if (ind == gr_slatUserDefnV1)
+ {
+ ind = gr_slatUserDefn;
+ subindex = 0;
++ if (seg->numAttrs() == 0)
++ return;
+ }
+ else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
+ {
+ int indx = ind - gr_slatJStretch;
+ return setJustify(seg, indx / 5, indx % 5, value);
+ }
+
+ switch (ind)
+@@ -416,32 +420,32 @@ bool Slot::sibling(Slot *ap)
+ }
+
+ bool Slot::removeChild(Slot *ap)
+ {
+ if (this == ap || !m_child) return false;
+ else if (ap == m_child)
+ {
+ Slot *nSibling = m_child->nextSibling();
+- m_child->sibling(NULL);
++ m_child->removeSibling(nSibling);
+ m_child = nSibling;
+ return true;
+ }
+ else
+ return m_child->removeSibling(ap);
+ return true;
+ }
+
+ bool Slot::removeSibling(Slot *ap)
+ {
+ if (this == ap || !m_sibling) return false;
+ else if (ap == m_sibling)
+ {
+ m_sibling = m_sibling->nextSibling();
+- ap->sibling(NULL);
++ if (m_sibling) ap->removeSibling(m_sibling);
+ return true;
+ }
+ else
+ return m_sibling->removeSibling(ap);
+ return true;
+ }
+
+ void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
+diff --git a/gfx/graphite2/src/TtfUtil.cpp b/gfx/graphite2/src/TtfUtil.cpp
+--- a/gfx/graphite2/src/TtfUtil.cpp
++++ b/gfx/graphite2/src/TtfUtil.cpp
+@@ -884,18 +884,19 @@ const void * FindCmapSubtable(const void
+ }
+
+ return 0;
+ }
+
+ /*----------------------------------------------------------------------------------------------
+ Check the Microsoft Unicode subtable for expected values
+ ----------------------------------------------------------------------------------------------*/
+-bool CheckCmapSubtable4(const void * pCmapSubtable4, size_t table_len /*, unsigned int maxgid*/)
++bool CheckCmapSubtable4(const void * pCmapSubtable4, const void * pCmapEnd /*, unsigned int maxgid*/)
+ {
++ size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable4;
+ if (!pCmapSubtable4) return false;
+ const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable4);
+ // Bob H say some freeware TT fonts have version 1 (eg, CALIGULA.TTF)
+ // so don't check subtable version. 21 Mar 2002 spec changes version to language.
+ if (be::swap(pTable->format) != 4) return false;
+ const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtable4);
+ uint16 length = be::swap(pTable4->length);
+ if (length > table_len)
+@@ -1044,17 +1045,17 @@ unsigned int CmapSubtable4NextCodepoint(
+ *pRangeKey = nRange - 1;
+ return 0xFFFF;
+ }
+
+ int iRange = (pRangeKey) ? *pRangeKey : 0;
+ // Just in case we have a bad key:
+ while (iRange > 0 && be::peek<uint16>(pStartCode + iRange) > nUnicodePrev)
+ iRange--;
+- while (be::peek<uint16>(pTable->end_code + iRange) < nUnicodePrev)
++ while (iRange < nRange - 1 && be::peek<uint16>(pTable->end_code + iRange) < nUnicodePrev)
+ iRange++;
+
+ // Now iRange is the range containing nUnicodePrev.
+ unsigned int nStartCode = be::peek<uint16>(pStartCode + iRange);
+ unsigned int nEndCode = be::peek<uint16>(pTable->end_code + iRange);
+
+ if (nStartCode > nUnicodePrev)
+ // Oops, nUnicodePrev is not in the cmap! Adjust so we get a reasonable
+@@ -1069,36 +1070,37 @@ unsigned int CmapSubtable4NextCodepoint(
+ return nUnicodePrev + 1;
+ }
+
+ // Otherwise the next codepoint is the first one in the next range.
+ // There is guaranteed to be a next range because there must be one that
+ // ends with 0xFFFF.
+ if (pRangeKey)
+ *pRangeKey = iRange + 1;
+- return be::peek<uint16>(pStartCode + iRange + 1);
++ return (iRange + 1 >= nRange) ? 0xFFFF : be::peek<uint16>(pStartCode + iRange + 1);
+ }
+
+ /*----------------------------------------------------------------------------------------------
+ Check the Microsoft UCS-4 subtable for expected values.
+ ----------------------------------------------------------------------------------------------*/
+-bool CheckCmapSubtable12(const void *pCmapSubtable12, size_t table_len /*, unsigned int maxgid*/)
++bool CheckCmapSubtable12(const void *pCmapSubtable12, const void *pCmapEnd /*, unsigned int maxgid*/)
+ {
++ size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable12;
+ if (!pCmapSubtable12) return false;
+ const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable12);
+ if (be::swap(pTable->format) != 12)
+ return false;
+ const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmapSubtable12);
+ uint32 length = be::swap(pTable12->length);
+ if (length > table_len)
+ return false;
+ if (length < sizeof(Sfnt::CmapSubTableFormat12))
+ return false;
+ uint32 num_groups = be::swap(pTable12->num_groups);
+- if (length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3))
++ if (num_groups > 0x10000000 || length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3))
+ return false;
+ #if 0
+ for (unsigned int i = 0; i < num_groups; ++i)
+ {
+ if (be::swap(pTable12->group[i].end_char_code) - be::swap(pTable12->group[i].start_char_code) + be::swap(pTable12->group[i].start_glyph_id) > maxgid)
+ return false;
+ if (i > 0 && be::swap(pTable12->group[i].start_char_code) <= be::swap(pTable12->group[i-1].end_char_code))
+ return false;
+@@ -1161,17 +1163,17 @@ unsigned int CmapSubtable12NextCodepoint
+ *pRangeKey = nRange;
+ return 0x10FFFF;
+ }
+
+ int iRange = (pRangeKey) ? *pRangeKey : 0;
+ // Just in case we have a bad key:
+ while (iRange > 0 && be::swap(pTable->group[iRange].start_char_code) > nUnicodePrev)
+ iRange--;
+- while (be::swap(pTable->group[iRange].end_char_code) < nUnicodePrev)
++ while (iRange < nRange - 1 && be::swap(pTable->group[iRange].end_char_code) < nUnicodePrev)
+ iRange++;
+
+ // Now iRange is the range containing nUnicodePrev.
+
+ unsigned int nStartCode = be::swap(pTable->group[iRange].start_char_code);
+ unsigned int nEndCode = be::swap(pTable->group[iRange].end_char_code);
+
+ if (nStartCode > nUnicodePrev)
+diff --git a/gfx/graphite2/src/call_machine.cpp b/gfx/graphite2/src/call_machine.cpp
+--- a/gfx/graphite2/src/call_machine.cpp
++++ b/gfx/graphite2/src/call_machine.cpp
+@@ -67,32 +67,34 @@ using namespace vm;
+ struct regbank {
+ slotref is;
+ slotref * map;
+ SlotMap & smap;
+ slotref * const map_base;
+ const instr * & ip;
+ uint8 direction;
+ int8 flags;
++ Machine::status_t & status;
+ };
+
+ typedef bool (* ip_t)(registers);
+
+ // Pull in the opcode definitions
+ // We pull these into a private namespace so these otherwise common names dont
+ // pollute the toplevel namespace.
+ namespace {
+ #define smap reg.smap
+ #define seg smap.segment
+ #define is reg.is
+ #define ip reg.ip
+ #define map reg.map
+ #define mapb reg.map_base
+ #define flags reg.flags
+ #define dir reg.direction
++#define status reg.status
+
+ #include "inc/opcodes.h"
+
+ #undef smap
+ #undef seg
+ #undef is
+ #undef ip
+ #undef map
+@@ -108,17 +110,17 @@ Machine::stack_t Machine::run(const ins
+ {
+ assert(program != 0);
+
+ // Declare virtual machine registers
+ const instr * ip = program-1;
+ const byte * dp = data;
+ stack_t * sp = _stack + Machine::STACK_GUARD,
+ * const sb = sp;
+- regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0};
++ regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0, _status};
+
+ // Run the program
+ while ((reinterpret_cast<ip_t>(*++ip))(dp, sp, sb, reg)) {}
+ const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
+
+ check_final_stack(sp);
+ map = reg.map;
+ *map = reg.is;
+diff --git a/gfx/graphite2/src/direct_machine.cpp b/gfx/graphite2/src/direct_machine.cpp
+--- a/gfx/graphite2/src/direct_machine.cpp
++++ b/gfx/graphite2/src/direct_machine.cpp
+@@ -57,36 +57,37 @@ using namespace vm;
+ namespace {
+
+ const void * direct_run(const bool get_table_mode,
+ const instr * program,
+ const byte * data,
+ Machine::stack_t * stack,
+ slotref * & __map,
+ uint8 _dir,
++ Machine::status_t & status,
+ SlotMap * __smap=0)
+ {
+ // We need to define and return to opcode table from within this function
+ // other inorder to take the addresses of the instruction bodies.
+ #include "inc/opcode_table.h"
+ if (get_table_mode)
+ return opcode_table;
+
+ // Declare virtual machine registers
+- const instr * ip = program;
+- const byte * dp = data;
+- Machine::stack_t * sp = stack + Machine::STACK_GUARD,
+- * const sb = sp;
+- SlotMap & smap = *__smap;
+- Segment & seg = smap.segment;
+- slotref is = *__map,
+- * map = __map,
+- * const mapb = smap.begin()+smap.context();
+- uint8 dir = _dir;
+- int8 flags = 0;
++ const instr * ip = program;
++ const byte * dp = data;
++ Machine::stack_t * sp = stack + Machine::STACK_GUARD,
++ * const sb = sp;
++ SlotMap & smap = *__smap;
++ Segment & seg = smap.segment;
++ slotref is = *__map,
++ * map = __map,
++ * const mapb = smap.begin()+smap.context();
++ uint8 dir = _dir;
++ int8 flags = 0;
+
+ // start the program
+ goto **ip;
+
+ // Pull in the opcode definitions
+ #include "inc/opcodes.h"
+
+ end:
+@@ -95,25 +96,26 @@ const void * direct_run(const bool
+ return sp;
+ }
+
+ }
+
+ const opcode_t * Machine::getOpcodeTable() throw()
+ {
+ slotref * dummy;
+- return static_cast<const opcode_t *>(direct_run(true, 0, 0, 0, dummy, 0));
++ Machine::status_t dumstat = Machine::finished;
++ return static_cast<const opcode_t *>(direct_run(true, 0, 0, 0, dummy, 0, dumstat));
+ }
+
+
+ Machine::stack_t Machine::run(const instr * program,
+ const byte * data,
+ slotref * & is)
+ {
+ assert(program != 0);
+
+ const stack_t *sp = static_cast<const stack_t *>(
+- direct_run(false, program, data, _stack, is, _map.dir(), &_map));
++ direct_run(false, program, data, _stack, is, _map.dir(), _status, &_map));
+ const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
+ check_final_stack(sp);
+ return ret;
+ }
+
+diff --git a/gfx/graphite2/src/inc/Code.h b/gfx/graphite2/src/inc/Code.h
+--- a/gfx/graphite2/src/inc/Code.h
++++ b/gfx/graphite2/src/inc/Code.h
+@@ -109,17 +109,17 @@ public:
+ int32 run(Machine &m, slotref * & map) const;
+
+ CLASS_NEW_DELETE;
+ };
+
+ inline
+ size_t Machine::Code::estimateCodeDataOut(size_t n_bc)
+ {
+- return n_bc * (sizeof(instr)+sizeof(byte));
++ return (n_bc + 1) * (sizeof(instr)+sizeof(byte));
+ }
+
+
+ inline Machine::Code::Code() throw()
+ : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
+ _status(loaded), _constraint(false), _modify(false), _delete(false),
+ _own(false)
+ {
+diff --git a/gfx/graphite2/src/inc/Machine.h b/gfx/graphite2/src/inc/Machine.h
+--- a/gfx/graphite2/src/inc/Machine.h
++++ b/gfx/graphite2/src/inc/Machine.h
+@@ -135,17 +135,18 @@ public:
+
+ class Code;
+
+ enum status_t {
+ finished = 0,
+ stack_underflow,
+ stack_not_empty,
+ stack_overflow,
+- slot_offset_out_bounds
++ slot_offset_out_bounds,
++ died_early
+ };
+
+ Machine(SlotMap &) throw();
+ static const opcode_t * getOpcodeTable() throw();
+
+ CLASS_NEW_DELETE;
+
+ SlotMap & slotMap() const throw();
+diff --git a/gfx/graphite2/src/inc/TtfUtil.h b/gfx/graphite2/src/inc/TtfUtil.h
+--- a/gfx/graphite2/src/inc/TtfUtil.h
++++ b/gfx/graphite2/src/inc/TtfUtil.h
+@@ -132,21 +132,21 @@ public:
+ int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId,
+ int *nameIdList, int cNameIds, short *langIdList);
+ void SwapWString(void * pWStr, size_t nSize = 0); // throw (std::invalid_argument);
+ #endif
+
+ ////////////////////////////////// cmap lookup tools
+ const void * FindCmapSubtable(const void * pCmap, int nPlatformId = 3,
+ int nEncodingId = 1, size_t length = 0);
+- bool CheckCmapSubtable4(const void * pCmap31, size_t table_len /*, unsigned int maxgid*/);
++ bool CheckCmapSubtable4(const void * pCmap31, const void * pCmapEnd /*, unsigned int maxgid*/);
+ gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey = 0);
+ unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId,
+ int * pRangeKey = 0);
+- bool CheckCmapSubtable12(const void *pCmap310, size_t table_len /*, unsigned int maxgid*/);
++ bool CheckCmapSubtable12(const void *pCmap310, const void * pCmapEnd /*, unsigned int maxgid*/);
+ gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey = 0);
+ unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId,
+ int * pRangeKey = 0);
+
+ ///////////////////////////////// horizontal metric data for a glyph
+ bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize,
+ const void * pHhea, int & nLsb, unsigned int & nAdvWid);
+
+diff --git a/gfx/graphite2/src/inc/opcodes.h b/gfx/graphite2/src/inc/opcodes.h
+--- a/gfx/graphite2/src/inc/opcodes.h
++++ b/gfx/graphite2/src/inc/opcodes.h
+@@ -71,17 +71,17 @@ of the License or (at your option) any l
+ #define use_params(n) dp += n
+
+ #define declare_params(n) const byte * param = dp; \
+ use_params(n);
+
+ #define push(n) { *++sp = n; }
+ #define pop() (*sp--)
+ #define slotat(x) (map[(x)])
+-#define DIE { is=seg.last(); EXIT(1); }
++#define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); }
+ #define POSITIONED 1
+
+ STARTOP(nop)
+ do {} while (0);
+ ENDOP
+
+ STARTOP(push_byte)
+ declare_params(1);
+@@ -387,30 +387,30 @@ STARTOP(attr_set)
+ ENDOP
+
+ STARTOP(attr_add)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const int val = int(pop());
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+- seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
++ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ int res = is->getAttr(&seg, slat, 0);
+ is->setAttr(&seg, slat, 0, val + res, smap);
+ ENDOP
+
+ STARTOP(attr_sub)
+ declare_params(1);
+ const attrCode slat = attrCode(uint8(*param));
+ const int val = int(pop());
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+- seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
++ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ int res = is->getAttr(&seg, slat, 0);
+ is->setAttr(&seg, slat, 0, res - val, smap);
+ ENDOP
+
+ STARTOP(attr_set_slot)
+ declare_params(1);
+@@ -429,17 +429,17 @@ STARTOP(iattr_set_slot)
+ ENDOP
+
+ STARTOP(push_slot_attr)
+ declare_params(2);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const int slot_ref = int8(param[1]);
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+- seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
++ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int res = slot->getAttr(&seg, slat, 0);
+ push(res);
+ }
+@@ -505,17 +505,17 @@ ENDOP
+
+ STARTOP(push_islot_attr)
+ declare_params(3);
+ const attrCode slat = attrCode(uint8(param[0]));
+ const int slot_ref = int8(param[1]),
+ idx = uint8(param[2]);
+ if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+ {
+- seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
++ seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+ flags |= POSITIONED;
+ }
+ slotref slot = slotat(slot_ref);
+ if (slot)
+ {
+ int res = slot->getAttr(&seg, slat, idx);
+ push(res);
+ }
+
diff --git a/gnu/packages/patches/ilmbase-fix-tests.patch b/gnu/packages/patches/ilmbase-fix-tests.patch
new file mode 100644
index 0000000000..fcaa37d201
--- /dev/null
+++ b/gnu/packages/patches/ilmbase-fix-tests.patch
@@ -0,0 +1,149 @@
+Fix FTBFS on i686-linux due to rounding issue (see references).
+
+Fixes Guix bug #22049 (see below).
+
+Copied from Debian.
+
+Source:
+https://sources.debian.net/src/ilmbase/2.2.0-11/debian/patches/testBoxAlgo.patch/
+https://sources.debian.net/src/ilmbase/2.2.0-11/debian/patches/testBox.patch/
+
+References:
+https://lists.nongnu.org/archive/html/openexr-devel/2015-12/msg00001.html
+https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22049
+https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=815712
+https://anonscm.debian.org/cgit/pkg-phototools/ilmbase.git/commit/?id=ab28bb45cdad8adc32e345b777ab8e692b1d9a9c
+
+---
+
+Subject: testBoxAlgo: allow fuzzy match of b12 == b2
+From: Steven Chamberlain <steven@pyro.eu.org>
+Date: Wed, 24 Feb 2016 01:04:11 +0000
+
+Also fix a pre-existing typo.
+
+Index: ilmbase/ImathTest/testBoxAlgo.cpp
+===================================================================
+--- ilmbase.orig/ImathTest/testBoxAlgo.cpp
++++ ilmbase/ImathTest/testBoxAlgo.cpp
+@@ -886,10 +886,11 @@ boxMatrixTransform ()
+
+ assert (approximatelyEqual (b2.min, b4.min, e));
+ assert (approximatelyEqual (b2.max, b4.max, e));
+- assert (approximatelyEqual (b3.max, b4.max, e));
++ assert (approximatelyEqual (b3.min, b4.min, e));
+ assert (approximatelyEqual (b3.max, b4.max, e));
+
+- assert (b21 == b2);
++ assert (approximatelyEqual (b2.min, b21.min, e));
++ assert (approximatelyEqual (b2.max, b21.max, e));
+ assert (b31 == b3);
+
+ M[0][3] = 1;
+
+---
+
+Subject: testBox: allow fuzzy comparison of floats, doubles
+From: Steven Chamberlain <steven@pyro.eu.org>
+Date: Wed, 24 Feb 2016 01:10:11 +0000
+
+Allow for inexact values, as long as the error is smaller than the
+epsilon of the data type.
+
+On 32-bit x86, allow even greater discrepency at double
+precision, due to possible double-rounding. See
+https://lists.nongnu.org/archive/html/openexr-devel/2015-12/msg00001.html
+
+Index: ilmbase/ImathTest/testBox.cpp
+===================================================================
+--- ilmbase.orig/ImathTest/testBox.cpp
++++ ilmbase/ImathTest/testBox.cpp
+@@ -47,6 +47,58 @@ using namespace IMATH_INTERNAL_NAMESPACE
+
+ namespace {
+
++template <class T>
++bool
++approximatelyEqual (const T &p1, const T &p2)
++{
++ /* int and short should be exact */
++ return (p1 == p2);
++}
++
++bool
++approximatelyEqual (const Vec2<float> &p1, const Vec2<float> &p2)
++{
++ float e = limits<float>::epsilon();
++ float m = 0;
++
++ for (int i = 0; i < 2; ++i)
++ {
++ m = max (m, abs (p1[i]));
++ m = max (m, abs (p2[i]));
++ }
++
++ for (int i = 0; i < 2; ++i)
++ if (!equalWithAbsError (p1[i], p2[i], m * e))
++ return false;
++
++ return true;
++}
++
++bool
++approximatelyEqual (const Vec2<double> &p1, const Vec2<double> &p2)
++{
++#if defined(__i386__) || defined(_M_IX86)
++ /* double-rounding on 32-bit x86 may cause larger error:
++ use epsilon of float rather than double */
++ double e = limits<float>::epsilon();
++#else
++ double e = limits<double>::epsilon();
++#endif
++ double m = 0;
++
++ for (int i = 0; i < 2; ++i)
++ {
++ m = max (m, abs (p1[i]));
++ m = max (m, abs (p2[i]));
++ }
++
++ for (int i = 0; i < 2; ++i)
++ if (!equalWithAbsError (p1[i], p2[i], m * e))
++ return false;
++
++ return true;
++}
++
+ //
+ // Test case generation utility - create a vector of IMATH_INTERNAL_NAMESPACE::Vec{2,3,4}
+ // with all permutations of integers 1..T::dimensions().
+@@ -250,7 +302,8 @@ testExtendByPoint(const char *type)
+
+ IMATH_INTERNAL_NAMESPACE::Box<T> b;
+ b.extendBy(p);
+- assert(b.min == p && b.max == p);
++ assert (approximatelyEqual (b.min, p));
++ assert (approximatelyEqual (b.max, p));
+ }
+
+ //
+@@ -283,7 +336,8 @@ testExtendByPoint(const char *type)
+
+ b.extendBy(p);
+
+- assert(b.min == min && b.max == max);
++ assert (approximatelyEqual (b.min, min));
++ assert (approximatelyEqual (b.max, max));
+ }
+ }
+ }
+@@ -358,7 +412,8 @@ testExtendByBox(const char *type)
+ }
+ b.extendBy(IMATH_INTERNAL_NAMESPACE::Box<T>(p0, p1));
+
+- assert(b.min == min && b.max == max);
++ assert (approximatelyEqual (b.min, min));
++ assert (approximatelyEqual (b.max, max));
+ }
+ }
+ }
diff --git a/gnu/packages/patches/jasper-CVE-2016-1577.patch b/gnu/packages/patches/jasper-CVE-2016-1577.patch
new file mode 100644
index 0000000000..75bbd526af
--- /dev/null
+++ b/gnu/packages/patches/jasper-CVE-2016-1577.patch
@@ -0,0 +1,19 @@
+Description: CVE-2016-1577: Prevent double-free in jas_iccattrval_destroy()
+Origin: vendor, http://www.openwall.com/lists/oss-security/2016/03/03/12
+Bug-Ubuntu: https://launchpad.net/bugs/1547865
+Bug-Debian: https://bugs.debian.org/816625
+Forwarded: not-needed
+Author: Tyler Hicks <tyhicks@canonical.com>
+Reviewed-by: Salvatore Bonaccorso <carnil@debian.org>
+Last-Update: 2016-03-05
+
+--- a/src/libjasper/base/jas_icc.c
++++ b/src/libjasper/base/jas_icc.c
+@@ -300,6 +300,7 @@ jas_iccprof_t *jas_iccprof_load(jas_stre
+ if (jas_iccprof_setattr(prof, tagtabent->tag, attrval))
+ goto error;
+ jas_iccattrval_destroy(attrval);
++ attrval = 0;
+ } else {
+ #if 0
+ jas_eprintf("warning: skipping unknown tag type\n");
diff --git a/gnu/packages/patches/jasper-CVE-2016-2089.patch b/gnu/packages/patches/jasper-CVE-2016-2089.patch
new file mode 100644
index 0000000000..95d4b61111
--- /dev/null
+++ b/gnu/packages/patches/jasper-CVE-2016-2089.patch
@@ -0,0 +1,90 @@
+Description: CVE-2016-2089: matrix rows_ NULL pointer dereference in jas_matrix_clip()
+Origin: vendor
+Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=1302636
+Bug-Debian: https://bugs.debian.org/812978
+Forwarded: not-needed
+Author: Tomas Hoger <thoger@redhat.com>
+Reviewed-by: Salvatore Bonaccorso <carnil@debian.org>
+Last-Update: 2016-03-05
+
+--- a/src/libjasper/base/jas_image.c
++++ b/src/libjasper/base/jas_image.c
+@@ -426,6 +426,10 @@ int jas_image_readcmpt(jas_image_t *imag
+ return -1;
+ }
+
++ if (!data->rows_) {
++ return -1;
++ }
++
+ if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) {
+ if (jas_matrix_resize(data, height, width)) {
+ return -1;
+@@ -479,6 +483,10 @@ int jas_image_writecmpt(jas_image_t *ima
+ return -1;
+ }
+
++ if (!data->rows_) {
++ return -1;
++ }
++
+ if (jas_matrix_numrows(data) != height || jas_matrix_numcols(data) != width) {
+ return -1;
+ }
+--- a/src/libjasper/base/jas_seq.c
++++ b/src/libjasper/base/jas_seq.c
+@@ -262,6 +262,10 @@ void jas_matrix_divpow2(jas_matrix_t *ma
+ int rowstep;
+ jas_seqent_t *data;
+
++ if (!matrix->rows_) {
++ return;
++ }
++
+ rowstep = jas_matrix_rowstep(matrix);
+ for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
+ rowstart += rowstep) {
+@@ -282,6 +286,10 @@ void jas_matrix_clip(jas_matrix_t *matri
+ jas_seqent_t *data;
+ int rowstep;
+
++ if (!matrix->rows_) {
++ return;
++ }
++
+ rowstep = jas_matrix_rowstep(matrix);
+ for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
+ rowstart += rowstep) {
+@@ -306,6 +314,10 @@ void jas_matrix_asr(jas_matrix_t *matrix
+ int rowstep;
+ jas_seqent_t *data;
+
++ if (!matrix->rows_) {
++ return;
++ }
++
+ assert(n >= 0);
+ rowstep = jas_matrix_rowstep(matrix);
+ for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
+@@ -325,6 +337,10 @@ void jas_matrix_asl(jas_matrix_t *matrix
+ int rowstep;
+ jas_seqent_t *data;
+
++ if (!matrix->rows_) {
++ return;
++ }
++
+ rowstep = jas_matrix_rowstep(matrix);
+ for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
+ rowstart += rowstep) {
+@@ -367,6 +383,10 @@ void jas_matrix_setall(jas_matrix_t *mat
+ int rowstep;
+ jas_seqent_t *data;
+
++ if (!matrix->rows_) {
++ return;
++ }
++
+ rowstep = jas_matrix_rowstep(matrix);
+ for (i = matrix->numrows_, rowstart = matrix->rows_[0]; i > 0; --i,
+ rowstart += rowstep) {
diff --git a/gnu/packages/patches/jasper-CVE-2016-2116.patch b/gnu/packages/patches/jasper-CVE-2016-2116.patch
new file mode 100644
index 0000000000..cdb616fb6a
--- /dev/null
+++ b/gnu/packages/patches/jasper-CVE-2016-2116.patch
@@ -0,0 +1,19 @@
+Description: CVE-2016-2116: Prevent jas_stream_t memory leak in jas_iccprof_createfrombuf()
+Origin: vendor, http://www.openwall.com/lists/oss-security/2016/03/03/12
+Bug-Debian: https://bugs.debian.org/816626
+Forwarded: not-needed
+Author: Tyler Hicks <tyhicks@canoonical.com>
+Reviewed-by: Salvatore Bonaccorso <carnil@debian.org>
+Last-Update: 2016-03-05
+
+--- a/src/libjasper/base/jas_icc.c
++++ b/src/libjasper/base/jas_icc.c
+@@ -1693,6 +1693,8 @@ jas_iccprof_t *jas_iccprof_createfrombuf
+ jas_stream_close(in);
+ return prof;
+ error:
++ if (in)
++ jas_stream_close(in);
+ return 0;
+ }
+
diff --git a/gnu/packages/patches/libotr-test-auth-fix.patch b/gnu/packages/patches/libotr-test-auth-fix.patch
new file mode 100644
index 0000000000..23b8d8308d
--- /dev/null
+++ b/gnu/packages/patches/libotr-test-auth-fix.patch
@@ -0,0 +1,15 @@
+Initialize the context in 'test_auth_clear'.
+Fixes the test suite on mips64el.
+
+Patch by Mark H Weaver <mhw@netris.org>
+
+--- libotr-4.1.1/tests/unit/test_auth.c.orig 2015-12-25 12:39:45.000000000 -0500
++++ libotr-4.1.1/tests/unit/test_auth.c 2016-03-17 18:53:10.169999706 -0400
+@@ -67,6 +67,7 @@
+ OtrlAuthInfo *auth = &ctx.auth;
+
+ /* API call. */
++ otrl_auth_new(&ctx);
+ otrl_auth_clear(auth);
+
+ ok(auth->authstate == OTRL_AUTHSTATE_NONE &&
diff --git a/gnu/packages/patches/mupdf-buildsystem-fix.patch b/gnu/packages/patches/mupdf-buildsystem-fix.patch
deleted file mode 100644
index 0b17dda911..0000000000
--- a/gnu/packages/patches/mupdf-buildsystem-fix.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-Since openjpeg doesn't seem to ship with a .pc file, provide an alternative.
-
---- a/ojp2_cppflags.sh 1970-01-01 01:00:00.000000000 +0100
-+++ b/ojp2_cppflags.sh 2014-09-13 22:56:38.842418777 +0200
-@@ -0,0 +1,7 @@
-+#!/bin/sh
-+
-+# Return the preprocessor flags to link against openjpeg.
-+
-+cpppath=$(echo ${NIX_STORE}/*-openjpeg-*/include/openjpeg-*)
-+
-+echo -I$cpppath
-
---- a/ojp2_ldflags.sh 1970-01-01 01:00:00.000000000 +0100
-+++ b/ojp2_ldflags.sh 2014-09-13 22:56:38.842418777 +0200
-@@ -0,0 +1,7 @@
-+#!/bin/sh
-+
-+# Return the linker flags to link against openjpeg.
-+
-+ldpath=$(echo ${NIX_STORE}/*-openjpeg-*/lib)
-+
-+echo -L$ldpath -lopenjp2
-
-Make use of the above alternatives, compile with gcc.
-
---- a/Makerules 2014-09-14 09:13:40.729149860 +0200
-+++ b/Makerules 2014-09-14 09:17:06.425156595 +0200
-@@ -75,12 +75,14 @@
-
- SYS_FREETYPE_CFLAGS = $(shell pkg-config --cflags freetype2)
- SYS_FREETYPE_LIBS = $(shell pkg-config --libs freetype2)
--SYS_OPENJPEG_CFLAGS = $(shell pkg-config --cflags libopenjp2)
--SYS_OPENJPEG_LIBS = $(shell pkg-config --libs libopenjp2)
-+SYS_OPENJPEG_CFLAGS = $(shell ./ojp2_cppflags.sh)
-+SYS_OPENJPEG_LIBS = $(shell ./ojp2_ldflags.sh)
- SYS_JBIG2DEC_LIBS = -ljbig2dec
- SYS_JPEG_LIBS = -ljpeg
- SYS_ZLIB_LIBS = -lz
-
-+CC = gcc
-+
- endif
-
- # The following section is an example of how to simply do cross-compilation
-
-Remove the -x11 from the built binaries, since X11 is implied on GNU. (This
-might change when Wayland gets more popular)
-
---- a/Makefile 2014-06-10 17:09:28.000000000 +0200
-+++ b/Makefile 2014-09-14 09:57:10.381235299 +0200
-@@ -255,7 +255,7 @@
- $(LINK_CMD)
-
- ifeq "$(HAVE_X11)" "yes"
--MUVIEW_X11 := $(OUT)/mupdf-x11
-+MUVIEW_X11 := $(OUT)/mupdf
- MUVIEW_X11_OBJ := $(addprefix $(OUT)/platform/x11/, x11_main.o x11_image.o pdfapp.o)
- $(MUVIEW_X11_OBJ) : $(FITZ_HDR) $(PDF_HDR)
- $(MUVIEW_X11) : $(MUPDF_LIB) $(THIRD_LIBS)
-@@ -263,7 +263,7 @@
- $(LINK_CMD) $(X11_LIBS)
-
- ifeq "$(HAVE_CURL)" "yes"
--MUVIEW_X11_CURL := $(OUT)/mupdf-x11-curl
-+MUVIEW_X11_CURL := $(OUT)/mupdf-curl
- MUVIEW_X11_CURL_OBJ := $(addprefix $(OUT)/platform/x11/curl/, x11_main.o x11_image.o pdfapp.o curl_stream.o)
- $(MUVIEW_X11_CURL_OBJ) : $(FITZ_HDR) $(PDF_HDR)
- $(MUVIEW_X11_CURL) : $(MUPDF_LIB) $(THIRD_LIBS) $(CURL_LIB)
diff --git a/gnu/packages/patches/openssl-c-rehash-in.patch b/gnu/packages/patches/openssl-c-rehash-in.patch
new file mode 100644
index 0000000000..bd3d3178f1
--- /dev/null
+++ b/gnu/packages/patches/openssl-c-rehash-in.patch
@@ -0,0 +1,17 @@
+This patch removes the explicit reference to the 'perl' binary,
+such that OpenSSL does not retain a reference to Perl.
+
+The 'c_rehash' program is seldom used, but it is used nonetheless
+to create symbolic links to certificates, for instance in the 'nss-certs'
+package.
+
+--- openssl-1.0.2g/tools/c_rehash.in 2015-09-09 18:36:07.313316482 +0200
++++ openssl-1.0.2g/tools/c_rehash.in 2015-09-09 18:36:28.965458458 +0200
+@@ -1,4 +1,6 @@
+-#!/usr/local/bin/perl
++eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
++ & eval 'exec perl -wS "$0" $argv:q'
++ if 0;
+
+ # Perl c_rehash script, scan all files in a directory
+ # and add symbolic links to their hash values.
diff --git a/gnu/packages/patches/perl-CVE-2016-2381.patch b/gnu/packages/patches/perl-CVE-2016-2381.patch
new file mode 100644
index 0000000000..99d1944a5d
--- /dev/null
+++ b/gnu/packages/patches/perl-CVE-2016-2381.patch
@@ -0,0 +1,116 @@
+Fix CVE-2016-2381 (ambiguous handling of duplicated environment variables).
+
+Copied from upstream:
+http://perl5.git.perl.org/perl.git/commit/ae37b791a73a9e78dedb89fb2429d2628cf58076
+
+References:
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2381
+http://www.nntp.perl.org/group/perl.perl5.porters/2016/03/msg234747.html
+https://security-tracker.debian.org/tracker/CVE-2016-2381
+
+---
+
+From 1237ea93fb2475a5ae576d5ee1358a5bb4ebe426 Mon Sep 17 00:00:00 2001
+From: Tony Cook <tony@develop-help.com>
+Date: Wed, 27 Jan 2016 11:52:15 +1100
+Subject: remove duplicate environment variables from environ
+
+If we see duplicate environment variables while iterating over
+environ[]:
+
+a) make sure we use the same value in %ENV that getenv() returns.
+
+Previously on a duplicate, %ENV would have the last entry for the name
+from environ[], but a typical getenv() would return the first entry.
+
+Rather than assuming all getenv() implementations return the first entry
+explicitly call getenv() to ensure they agree.
+
+b) remove duplicate entries from environ
+
+Previously if there was a duplicate definition for a name in environ[]
+setting that name in %ENV could result in an unsafe value being passed
+to a child process, so ensure environ[] has no duplicates.
+
+Patch-Name: fixes/CVE-2016-2381_duplicate_env.diff
+---
+ perl.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 49 insertions(+), 2 deletions(-)
+
+diff --git a/perl.c b/perl.c
+index 67d32ce..26aeb91 100644
+--- a/perl.c
++++ b/perl.c
+@@ -4277,23 +4277,70 @@ S_init_postdump_symbols(pTHX_ int argc, char **argv, char **env)
+ }
+ if (env) {
+ char *s, *old_var;
++ STRLEN nlen;
+ SV *sv;
++ HV *dups = newHV();
++
+ for (; *env; env++) {
+ old_var = *env;
+
+ if (!(s = strchr(old_var,'=')) || s == old_var)
+ continue;
++ nlen = s - old_var;
+
+ #if defined(MSDOS) && !defined(DJGPP)
+ *s = '\0';
+ (void)strupr(old_var);
+ *s = '=';
+ #endif
+- sv = newSVpv(s+1, 0);
+- (void)hv_store(hv, old_var, s - old_var, sv, 0);
++ if (hv_exists(hv, old_var, nlen)) {
++ const char *name = savepvn(old_var, nlen);
++
++ /* make sure we use the same value as getenv(), otherwise code that
++ uses getenv() (like setlocale()) might see a different value to %ENV
++ */
++ sv = newSVpv(PerlEnv_getenv(name), 0);
++
++ /* keep a count of the dups of this name so we can de-dup environ later */
++ if (hv_exists(dups, name, nlen))
++ ++SvIVX(*hv_fetch(dups, name, nlen, 0));
++ else
++ (void)hv_store(dups, name, nlen, newSViv(1), 0);
++
++ Safefree(name);
++ }
++ else {
++ sv = newSVpv(s+1, 0);
++ }
++ (void)hv_store(hv, old_var, nlen, sv, 0);
+ if (env_is_not_environ)
+ mg_set(sv);
+ }
++ if (HvKEYS(dups)) {
++ /* environ has some duplicate definitions, remove them */
++ HE *entry;
++ hv_iterinit(dups);
++ while ((entry = hv_iternext_flags(dups, 0))) {
++ STRLEN nlen;
++ const char *name = HePV(entry, nlen);
++ IV count = SvIV(HeVAL(entry));
++ IV i;
++ SV **valp = hv_fetch(hv, name, nlen, 0);
++
++ assert(valp);
++
++ /* try to remove any duplicate names, depending on the
++ * implementation used in my_setenv() the iteration might
++ * not be necessary, but let's be safe.
++ */
++ for (i = 0; i < count; ++i)
++ my_setenv(name, 0);
++
++ /* and set it back to the value we set $ENV{name} to */
++ my_setenv(name, SvPV_nolen(*valp));
++ }
++ }
++ SvREFCNT_dec_NN(dups);
+ }
+ #endif /* USE_ENVIRON_ARRAY */
+ #endif /* !PERL_MICRO */
diff --git a/gnu/packages/patches/procmail-ambiguous-getline-debian.patch b/gnu/packages/patches/procmail-ambiguous-getline-debian.patch
new file mode 100644
index 0000000000..5dc91b1919
--- /dev/null
+++ b/gnu/packages/patches/procmail-ambiguous-getline-debian.patch
@@ -0,0 +1,61 @@
+Rename getline() to procmail_getline() to avoid namespace clash with
+POSIX getline(). Fixes FTBFS.
+
+Copied from Debian:
+http://sources.debian.net/src/procmail/3.22-24/debian/patches/24/
+
+References:
+http://bugs.debian.org/549426
+
+--- a/src/fields.c
++++ b/src/fields.c
+@@ -110,16 +110,16 @@
+ /* try and append one valid field to rdheader from stdin */
+ int readhead P((void))
+ { int idlen;
+- getline();
++ procmail_getline();
+ if((idlen=breakfield(buf,buffilled))<=0) /* not the start of a valid field */
+ return 0;
+ if(idlen==STRLEN(FROM)&&eqFrom_(buf)) /* it's a From_ line */
+ { if(rdheader)
+ return 0; /* the From_ line was a fake! */
+- for(;buflast=='>';getline()); /* gather continued >From_ lines */
++ for(;buflast=='>';procmail_getline()); /* gather continued >From_ lines */
+ }
+ else
+- for(;;getline()) /* get the rest of the continued field */
++ for(;;procmail_getline()) /* get the rest of the continued field */
+ { switch(buflast) /* will this line be continued? */
+ { case ' ':case '\t': /* yep, it sure is */
+ continue;
+--- a/src/formail.c
++++ b/src/formail.c
+@@ -819,7 +819,7 @@
+ { if(split) /* gobble up the next start separator */
+ { buffilled=0;
+ #ifdef sMAILBOX_SEPARATOR
+- getline();buffilled=0; /* but only if it's defined */
++ procmail_getline();buffilled=0; /* but only if it's defined */
+ #endif
+ if(buflast!=EOF) /* if any */
+ goto splitit;
+--- a/src/formisc.c
++++ b/src/formisc.c
+@@ -115,7 +115,7 @@
+ buf[buffilled++]=c;
+ }
+
+-int getline P((void)) /* read a newline-terminated line */
++int procmail_getline P((void)) /* read a newline-terminated line */
+ { if(buflast==EOF) /* at the end of our Latin already? */
+ { loadchar('\n'); /* fake empty line */
+ return EOF; /* spread the word */
+--- a/src/formisc.h
++++ b/src/formisc.h
+@@ -17,4 +17,4 @@
+ char*
+ skipwords P((char*start));
+ int
+- getline P((void));
++ procmail_getline P((void));
diff --git a/gnu/packages/patches/python-rarfile-fix-tests.patch b/gnu/packages/patches/python-rarfile-fix-tests.patch
new file mode 100644
index 0000000000..8ae8894009
--- /dev/null
+++ b/gnu/packages/patches/python-rarfile-fix-tests.patch
@@ -0,0 +1,14 @@
+There is no test.sh, but there are test1.sh and test2.sh.
+
+diff --git a/test/Makefile b/test/Makefile
+index 027bc5f..5383db3 100644
+--- a/test/Makefile
++++ b/test/Makefile
+@@ -1,5 +1,6 @@
+ test:
+- ./test.sh
++ ./test1.sh
++ ./test2.sh
+
+ clean:
+ rm -rf __pycache__
diff --git a/gnu/packages/patches/scribus-qobject.patch b/gnu/packages/patches/scribus-qobject.patch
deleted file mode 100644
index 91be932f1b..0000000000
--- a/gnu/packages/patches/scribus-qobject.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-See upstream bug report: http://bugs.scribus.net/view.php?id=13102
-
-scribus/sclayer.cpp | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/scribus/sclayer.cpp b/scribus/sclayer.cpp
-index 502112b..4da7bd5 100644
---- a/scribus/sclayer.cpp
-+++ b/scribus/sclayer.cpp
-@@ -9,6 +9,7 @@ for which a new license (GPL+exception) is in place.
-
- #include <QHash> //necessary to avoid msvc warnings induced by SCRIBUS_API on ScLayers + early instanciation of templates
- #include <QVector> //necessary to avoid msvc warnings induced by SCRIBUS_API on ScLayers + early instanciation of templates
-+#include <QObject>
- #include <QtAlgorithms>
-
- ScLayer::ScLayer(void)
diff --git a/gnu/packages/patches/vorbis-tools-CVE-2015-6749.patch b/gnu/packages/patches/vorbis-tools-CVE-2015-6749.patch
new file mode 100644
index 0000000000..bcddcbfd70
--- /dev/null
+++ b/gnu/packages/patches/vorbis-tools-CVE-2015-6749.patch
@@ -0,0 +1,44 @@
+Upstream fix for CVE-2015-6749.
+https://trac.xiph.org/ticket/2212
+
+From 04815d3e1bfae3a6cdfb2c25358a5a72b61299f7 Mon Sep 17 00:00:00 2001
+From: Mark Harris <mark.hsj@gmail.com>
+Date: Sun, 30 Aug 2015 05:54:46 -0700
+Subject: [PATCH] oggenc: Fix large alloca on bad AIFF input
+
+Fixes #2212
+---
+ oggenc/audio.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/oggenc/audio.c b/oggenc/audio.c
+index 477da8c..4921fb9 100644
+--- a/oggenc/audio.c
++++ b/oggenc/audio.c
+@@ -245,8 +245,8 @@ static int aiff_permute_matrix[6][6] =
+ int aiff_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen)
+ {
+ int aifc; /* AIFC or AIFF? */
+- unsigned int len;
+- unsigned char *buffer;
++ unsigned int len, readlen;
++ unsigned char buffer[22];
+ unsigned char buf2[8];
+ aiff_fmt format;
+ aifffile *aiff = malloc(sizeof(aifffile));
+@@ -269,9 +269,9 @@ int aiff_open(FILE *in, oe_enc_opt *opt, unsigned char *buf, int buflen)
+ return 0; /* Weird common chunk */
+ }
+
+- buffer = alloca(len);
+-
+- if(fread(buffer,1,len,in) < len)
++ readlen = len < sizeof(buffer) ? len : sizeof(buffer);
++ if(fread(buffer,1,readlen,in) < readlen ||
++ (len > readlen && !seek_forward(in, len-readlen)))
+ {
+ fprintf(stderr, _("Warning: Unexpected EOF in reading AIFF header\n"));
+ return 0;
+--
+2.5.0
+