summary refs log tree commit diff
path: root/gnu/packages/patches
diff options
context:
space:
mode:
authorMarius Bakke <mbakke@fastmail.com>2016-11-30 18:24:32 +0100
committerMarius Bakke <mbakke@fastmail.com>2016-11-30 18:24:32 +0100
commit8a7cbc882a75d7f9f1fe960552dea47acf347b0a (patch)
treeded8c9116d357b38fd23b8c0cc312863fe68c9b5 /gnu/packages/patches
parent3084a9908434e4e7123d2fd3881c798977abedb9 (diff)
parent72f0c5ea3c0272a93436ad3c04a281d1237a9593 (diff)
downloadguix-8a7cbc882a75d7f9f1fe960552dea47acf347b0a.tar.gz
Merge branch 'master' into staging
Diffstat (limited to 'gnu/packages/patches')
-rw-r--r--gnu/packages/patches/cairo-CVE-2016-9082.patch122
-rw-r--r--gnu/packages/patches/cyrus-sasl-CVE-2013-4122.patch130
-rw-r--r--gnu/packages/patches/gcj-arm-mode.patch36
-rw-r--r--gnu/packages/patches/gst-plugins-good-fix-crashes.patch1047
-rw-r--r--gnu/packages/patches/gst-plugins-good-fix-invalid-read.patch37
-rw-r--r--gnu/packages/patches/gst-plugins-good-fix-signedness.patch58
-rw-r--r--gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch319
-rw-r--r--gnu/packages/patches/ldc-disable-tests.patch50
-rw-r--r--gnu/packages/patches/python-2.7-site-prefixes.patch26
-rw-r--r--gnu/packages/patches/python-rarfile-fix-tests.patch14
10 files changed, 1792 insertions, 47 deletions
diff --git a/gnu/packages/patches/cairo-CVE-2016-9082.patch b/gnu/packages/patches/cairo-CVE-2016-9082.patch
new file mode 100644
index 0000000000..ad83404194
--- /dev/null
+++ b/gnu/packages/patches/cairo-CVE-2016-9082.patch
@@ -0,0 +1,122 @@
+From: Adrian Johnson <ajohnson@redneon.com>
+Date: Thu, 20 Oct 2016 21:12:30 +1030
+Subject: [PATCH] image: prevent invalid ptr access for > 4GB images
+
+Image data is often accessed using:
+
+  image->data + y * image->stride
+
+On 64-bit achitectures if the image data is > 4GB, this computation
+will overflow since both y and stride are 32-bit types.
+
+bug report: https://bugs.freedesktop.org/show_bug.cgi?id=98165
+patch: https://bugs.freedesktop.org/attachment.cgi?id=127421
+---
+ boilerplate/cairo-boilerplate.c     | 4 +++-
+ src/cairo-image-compositor.c        | 4 ++--
+ src/cairo-image-surface-private.h   | 2 +-
+ src/cairo-mesh-pattern-rasterizer.c | 2 +-
+ src/cairo-png.c                     | 2 +-
+ src/cairo-script-surface.c          | 3 ++-
+ 6 files changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
+index 7fdbf79..4804dea 100644
+--- a/boilerplate/cairo-boilerplate.c
++++ b/boilerplate/cairo-boilerplate.c
+@@ -42,6 +42,7 @@
+ #undef CAIRO_VERSION_H
+ #include "../cairo-version.h"
+ 
++#include <stddef.h>
+ #include <stdlib.h>
+ #include <ctype.h>
+ #include <assert.h>
+@@ -976,7 +977,8 @@ cairo_surface_t *
+ cairo_boilerplate_image_surface_create_from_ppm_stream (FILE *file)
+ {
+     char format;
+-    int width, height, stride;
++    int width, height;
++    ptrdiff_t stride;
+     int x, y;
+     unsigned char *data;
+     cairo_surface_t *image = NULL;
+diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
+index 48072f8..3ca0006 100644
+--- a/src/cairo-image-compositor.c
++++ b/src/cairo-image-compositor.c
+@@ -1575,7 +1575,7 @@ typedef struct _cairo_image_span_renderer {
+     pixman_image_t *src, *mask;
+     union {
+ 	struct fill {
+-	    int stride;
++	    ptrdiff_t stride;
+ 	    uint8_t *data;
+ 	    uint32_t pixel;
+ 	} fill;
+@@ -1594,7 +1594,7 @@ typedef struct _cairo_image_span_renderer {
+ 	struct finish {
+ 	    cairo_rectangle_int_t extents;
+ 	    int src_x, src_y;
+-	    int stride;
++	    ptrdiff_t stride;
+ 	    uint8_t *data;
+ 	} mask;
+     } u;
+diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
+index 8ca694c..7e78d61 100644
+--- a/src/cairo-image-surface-private.h
++++ b/src/cairo-image-surface-private.h
+@@ -71,7 +71,7 @@ struct _cairo_image_surface {
+ 
+     int width;
+     int height;
+-    int stride;
++    ptrdiff_t stride;
+     int depth;
+ 
+     unsigned owns_data : 1;
+diff --git a/src/cairo-mesh-pattern-rasterizer.c b/src/cairo-mesh-pattern-rasterizer.c
+index 1b63ca8..e7f0db6 100644
+--- a/src/cairo-mesh-pattern-rasterizer.c
++++ b/src/cairo-mesh-pattern-rasterizer.c
+@@ -470,7 +470,7 @@ draw_pixel (unsigned char *data, int width, int height, int stride,
+ 	tg += tg >> 16;
+ 	tb += tb >> 16;
+ 
+-	*((uint32_t*) (data + y*stride + 4*x)) = ((ta << 16) & 0xff000000) |
++	*((uint32_t*) (data + y*(ptrdiff_t)stride + 4*x)) = ((ta << 16) & 0xff000000) |
+ 	    ((tr >> 8) & 0xff0000) | ((tg >> 16) & 0xff00) | (tb >> 24);
+     }
+ }
+diff --git a/src/cairo-png.c b/src/cairo-png.c
+index 562b743..aa8c227 100644
+--- a/src/cairo-png.c
++++ b/src/cairo-png.c
+@@ -673,7 +673,7 @@ read_png (struct png_read_closure_t *png_closure)
+     }
+ 
+     for (i = 0; i < png_height; i++)
+-        row_pointers[i] = &data[i * stride];
++        row_pointers[i] = &data[i * (ptrdiff_t)stride];
+ 
+     png_read_image (png, row_pointers);
+     png_read_end (png, info);
+diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
+index ea0117d..91e4baa 100644
+--- a/src/cairo-script-surface.c
++++ b/src/cairo-script-surface.c
+@@ -1202,7 +1202,8 @@ static cairo_status_t
+ _write_image_surface (cairo_output_stream_t *output,
+ 		      const cairo_image_surface_t *image)
+ {
+-    int stride, row, width;
++    int row, width;
++    ptrdiff_t stride;
+     uint8_t row_stack[CAIRO_STACK_BUFFER_SIZE];
+     uint8_t *rowdata;
+     uint8_t *data;
+-- 
+2.1.4
+
diff --git a/gnu/packages/patches/cyrus-sasl-CVE-2013-4122.patch b/gnu/packages/patches/cyrus-sasl-CVE-2013-4122.patch
new file mode 100644
index 0000000000..fc72e42e03
--- /dev/null
+++ b/gnu/packages/patches/cyrus-sasl-CVE-2013-4122.patch
@@ -0,0 +1,130 @@
+Fix CVE-2013-4122.
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4122
+
+Patch copied from upstream source repository:
+https://github.com/cyrusimap/cyrus-sasl/commit/dedad73e5e7a75d01a5f3d5a6702ab8ccd2ff40d
+
+From dedad73e5e7a75d01a5f3d5a6702ab8ccd2ff40d Mon Sep 17 00:00:00 2001
+From: mancha <mancha1@hush.com>
+Date: Thu, 11 Jul 2013 10:08:07 +0100
+Subject: Handle NULL returns from glibc 2.17+ crypt()
+
+Starting with glibc 2.17 (eglibc 2.17), crypt() fails with EINVAL
+(w/ NULL return) if the salt violates specifications. Additionally,
+on FIPS-140 enabled Linux systems, DES/MD5-encrypted passwords
+passed to crypt() fail with EPERM (w/ NULL return).
+
+When using glibc's crypt(), check return value to avoid a possible
+NULL pointer dereference.
+
+Patch by mancha1@hush.com.
+---
+ pwcheck/pwcheck_getpwnam.c | 3 ++-
+ pwcheck/pwcheck_getspnam.c | 4 +++-
+ saslauthd/auth_getpwent.c  | 4 +++-
+ saslauthd/auth_shadow.c    | 8 +++-----
+ 4 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/pwcheck/pwcheck_getpwnam.c b/pwcheck/pwcheck_getpwnam.c
+index 4b34222..400289c 100644
+--- a/pwcheck/pwcheck_getpwnam.c
++++ b/pwcheck/pwcheck_getpwnam.c
+@@ -32,6 +32,7 @@ char *userid;
+ char *password;
+ {
+     char* r;
++    char* crpt_passwd;
+     struct passwd *pwd;
+ 
+     pwd = getpwnam(userid);
+@@ -41,7 +42,7 @@ char *password;
+     else if (pwd->pw_passwd[0] == '*') {
+ 	r = "Account disabled";
+     }
+-    else if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
++    else if (!(crpt_passwd = crypt(password, pwd->pw_passwd)) || strcmp(pwd->pw_passwd, (const char *)crpt_passwd) != 0) {
+ 	r = "Incorrect password";
+     }
+     else {
+diff --git a/pwcheck/pwcheck_getspnam.c b/pwcheck/pwcheck_getspnam.c
+index 2b11286..6d607bb 100644
+--- a/pwcheck/pwcheck_getspnam.c
++++ b/pwcheck/pwcheck_getspnam.c
+@@ -32,13 +32,15 @@ char *userid;
+ char *password;
+ {
+     struct spwd *pwd;
++    char *crpt_passwd;
+ 
+     pwd = getspnam(userid);
+     if (!pwd) {
+ 	return "Userid not found";
+     }
+     
+-    if (strcmp(pwd->sp_pwdp, crypt(password, pwd->sp_pwdp)) != 0) {
++    crpt_passwd = crypt(password, pwd->sp_pwdp);
++    if (!crpt_passwd || strcmp(pwd->sp_pwdp, (const char *)crpt_passwd) != 0) {
+ 	return "Incorrect password";
+     }
+     else {
+diff --git a/saslauthd/auth_getpwent.c b/saslauthd/auth_getpwent.c
+index fc8029d..d4ebe54 100644
+--- a/saslauthd/auth_getpwent.c
++++ b/saslauthd/auth_getpwent.c
+@@ -77,6 +77,7 @@ auth_getpwent (
+ {
+     /* VARIABLES */
+     struct passwd *pw;			/* pointer to passwd file entry */
++    char *crpt_passwd;			/* encrypted password */
+     int errnum;
+     /* END VARIABLES */
+   
+@@ -105,7 +106,8 @@ auth_getpwent (
+ 	}
+     }
+ 
+-    if (strcmp(pw->pw_passwd, (const char *)crypt(password, pw->pw_passwd))) {
++    crpt_passwd = crypt(password, pw->pw_passwd);
++    if (!crpt_passwd || strcmp(pw->pw_passwd, (const char *)crpt_passwd)) {
+ 	if (flags & VERBOSE) {
+ 	    syslog(LOG_DEBUG, "DEBUG: auth_getpwent: %s: invalid password", login);
+ 	}
+diff --git a/saslauthd/auth_shadow.c b/saslauthd/auth_shadow.c
+index 677131b..1988afd 100644
+--- a/saslauthd/auth_shadow.c
++++ b/saslauthd/auth_shadow.c
+@@ -210,8 +210,8 @@ auth_shadow (
+ 	RETURN("NO Insufficient permission to access NIS authentication database (saslauthd)");
+     }
+ 
+-    cpw = strdup((const char *)crypt(password, sp->sp_pwdp));
+-    if (strcmp(sp->sp_pwdp, cpw)) {
++    cpw = crypt(password, sp->sp_pwdp);
++    if (!cpw || strcmp(sp->sp_pwdp, (const char *)cpw)) {
+ 	if (flags & VERBOSE) {
+ 	    /*
+ 	     * This _should_ reveal the SHADOW_PW_LOCKED prefix to an
+@@ -221,10 +221,8 @@ auth_shadow (
+ 	    syslog(LOG_DEBUG, "DEBUG: auth_shadow: pw mismatch: '%s' != '%s'",
+ 		   sp->sp_pwdp, cpw);
+ 	}
+-	free(cpw);
+ 	RETURN("NO Incorrect password");
+     }
+-    free(cpw);
+ 
+     /*
+      * The following fields will be set to -1 if:
+@@ -286,7 +284,7 @@ auth_shadow (
+ 	RETURN("NO Invalid username");
+     }
+   
+-    if (strcmp(upw->upw_passwd, crypt(password, upw->upw_passwd)) != 0) {
++    if (!(cpw = crypt(password, upw->upw_passwd)) || (strcmp(upw->upw_passwd, (const char *)cpw) != 0)) {
+ 	if (flags & VERBOSE) {
+ 	    syslog(LOG_DEBUG, "auth_shadow: pw mismatch: %s != %s",
+ 		   password, upw->upw_passwd);
+-- 
+cgit v0.12
+
diff --git a/gnu/packages/patches/gcj-arm-mode.patch b/gnu/packages/patches/gcj-arm-mode.patch
new file mode 100644
index 0000000000..a3f999f7e9
--- /dev/null
+++ b/gnu/packages/patches/gcj-arm-mode.patch
@@ -0,0 +1,36 @@
+Taken from
+https://sources.debian.net/data/main/g/gcc-4.9/4.9.2-10/debian/patches/gcj-arm-mode.diff
+
+# DP: For armhf, force arm mode instead of thumb mode
+
+--- a/libjava/configure.host
++++ b/libjava/configure.host
+@@ -66,6 +66,9 @@
+     ;;
+ esac
+ 
++# on armhf force arm mode
++libgcj_flags="${libgcj_flags} -marm"
++
+ AM_RUNTESTFLAGS= 
+ 
+ # Set any host dependent compiler flags.
+--- a/gcc/java/lang-specs.h
++++ b/gcc/java/lang-specs.h
+@@ -47,7 +47,7 @@
+     %{.class|.zip|.jar|!fsyntax-only:jc1				\
+       %{.java|fsaw-java-file:%U.jar -fsource-filename=%i %<ffilelist-file} \
+       %{.class|.zip|.jar|ffilelist-file|fcompile-resource*:%i}		\
+-      %(jc1) %(cc1_options) %{I*} %{!findirect-dispatch:-faux-classpath %U.zip} \
++      %(jc1) %(cc1_options) -marm %{I*} %{!findirect-dispatch:-faux-classpath %U.zip} \
+       %{MD:-MD_} %{MMD:-MMD_} %{M} %{MM} %{MA} %{MT*} %{MF*}\
+       %(invoke_as)}",
+       0, 0, 0},
+--- a/libjava/libgcj.spec.in
++++ b/libjava/libgcj.spec.in
+@@ -9,4 +9,4 @@
+ %rename lib liborig
+ *lib: @LD_START_STATIC_SPEC@ @LIBGCJ_SPEC@ @LD_FINISH_STATIC_SPEC@ @LIBMATHSPEC@ @LDLIBICONV@ @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(libgcc) @LIBSTDCXXSPEC@ %(liborig)
+ 
+-*jc1: @HASH_SYNC_SPEC@ @DIVIDESPEC@ @CHECKREFSPEC@ @JC1GCSPEC@ @EXCEPTIONSPEC@ @BACKTRACESPEC@ @IEEESPEC@ @ATOMICSPEC@ @LIBGCJ_BC_SPEC@ -fkeep-inline-functions
++*jc1: @HASH_SYNC_SPEC@ @DIVIDESPEC@ @CHECKREFSPEC@ @JC1GCSPEC@ @EXCEPTIONSPEC@ @BACKTRACESPEC@ @IEEESPEC@ @ATOMICSPEC@ @LIBGCJ_BC_SPEC@ -fkeep-inline-functions -marm
diff --git a/gnu/packages/patches/gst-plugins-good-fix-crashes.patch b/gnu/packages/patches/gst-plugins-good-fix-crashes.patch
new file mode 100644
index 0000000000..c36a595608
--- /dev/null
+++ b/gnu/packages/patches/gst-plugins-good-fix-crashes.patch
@@ -0,0 +1,1047 @@
+Fixes upstream bug #774859 (flic decoder: Invalid memory read in
+flx_decode_chunks):
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774859
+
+Patch copied from upstream source repository:
+
+https://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=be670f0daf67304fb92c76aa09c30cae0bfd1fe4
+
+From be670f0daf67304fb92c76aa09c30cae0bfd1fe4 Mon Sep 17 00:00:00 2001
+From: Matthew Waters <matthew@centricular.com>
+Date: Wed, 23 Nov 2016 07:09:06 +1100
+Subject: [PATCH] flxdec: rewrite logic based on GstByteReader/Writer
+
+Solves overreading/writing the given arrays and will error out if the
+streams asks to do that.
+
+Also does more error checking that the stream is valid and won't
+overrun any allocated arrays.  Also mitigate integer overflow errors
+calculating allocation sizes.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774859
+---
+ gst/flx/flx_color.c |   1 -
+ gst/flx/flx_fmt.h   |  72 -------
+ gst/flx/gstflxdec.c | 610 ++++++++++++++++++++++++++++++++++++----------------
+ gst/flx/gstflxdec.h |   4 +-
+ 4 files changed, 427 insertions(+), 260 deletions(-)
+
+diff --git a/gst/flx/flx_color.c b/gst/flx/flx_color.c
+index 047bfdf..3a58135 100644
+--- a/gst/flx/flx_color.c
++++ b/gst/flx/flx_color.c
+@@ -101,7 +101,6 @@ flx_set_palette_vector (FlxColorSpaceConverter * flxpal, guint start, guint num,
+   } else {
+     memcpy (&flxpal->palvec[start * 3], newpal, grab * 3);
+   }
+-
+ }
+ 
+ void
+diff --git a/gst/flx/flx_fmt.h b/gst/flx/flx_fmt.h
+index 9ab31ba..abff200 100644
+--- a/gst/flx/flx_fmt.h
++++ b/gst/flx/flx_fmt.h
+@@ -123,78 +123,6 @@ typedef struct _FlxFrameType
+ } FlxFrameType;
+ #define FlxFrameTypeSize 10
+ 
+-#if G_BYTE_ORDER == G_BIG_ENDIAN 
+-#define LE_TO_BE_16(i16) ((guint16) (((i16) << 8) | ((i16) >> 8)))
+-#define LE_TO_BE_32(i32) \
+-    (((guint32) (LE_TO_BE_16((guint16) (i32))) << 16) | (LE_TO_BE_16((i32) >> 16)))
+-
+-#define FLX_FRAME_TYPE_FIX_ENDIANNESS(frm_type_p) \
+-    do { \
+-     (frm_type_p)->chunks = LE_TO_BE_16((frm_type_p)->chunks); \
+-     (frm_type_p)->delay = LE_TO_BE_16((frm_type_p)->delay); \
+-    } while(0)
+-
+-#define FLX_HUFFMAN_TABLE_FIX_ENDIANNESS(hffmn_table_p) \
+-    do { \
+-     (hffmn_table_p)->codelength = \
+-	LE_TO_BE_16((hffmn_table_p)->codelength); \
+-     (hffmn_table_p)->numcodes = LE_TO_BE_16((hffmn_table_p)->numcodes); \
+-    } while(0)
+-
+-#define FLX_SEGMENT_TABLE_FIX_ENDIANNESS(sgmnt_table_p) \
+-     ((sgmnt_table_p)->segments = LE_TO_BE_16((sgmnt_table_p)->segments))
+-
+-#define FLX_PREFIX_CHUNK_FIX_ENDIANNESS(prfx_chnk_p) \
+-    do { \
+-     (prfx_chnk_p)->chunks = LE_TO_BE_16((prfx_chnk_p)->chunks); \
+-    } while(0)
+-
+-#define FLX_FRAME_CHUNK_FIX_ENDIANNESS(frm_chnk_p) \
+-    do { \
+-     (frm_chnk_p)->size = LE_TO_BE_32((frm_chnk_p)->size); \
+-     (frm_chnk_p)->id = LE_TO_BE_16((frm_chnk_p)->id); \
+-    } while(0)
+-
+-#define FLX_HDR_FIX_ENDIANNESS(hdr_p) \
+-    do { \
+-     (hdr_p)->size = LE_TO_BE_32((hdr_p)->size); \
+-     (hdr_p)->type = LE_TO_BE_16((hdr_p)->type); \
+-     (hdr_p)->frames = LE_TO_BE_16((hdr_p)->frames); \
+-     (hdr_p)->width = LE_TO_BE_16((hdr_p)->width); \
+-     (hdr_p)->height = LE_TO_BE_16((hdr_p)->height); \
+-     (hdr_p)->depth = LE_TO_BE_16((hdr_p)->depth); \
+-     (hdr_p)->flags = LE_TO_BE_16((hdr_p)->flags); \
+-     (hdr_p)->speed = LE_TO_BE_32((hdr_p)->speed); \
+-     (hdr_p)->reserved1 = LE_TO_BE_16((hdr_p)->reserved1); \
+-     (hdr_p)->created = LE_TO_BE_32((hdr_p)->created); \
+-     (hdr_p)->creator = LE_TO_BE_32((hdr_p)->creator); \
+-     (hdr_p)->updated = LE_TO_BE_32((hdr_p)->updated); \
+-     (hdr_p)->updater = LE_TO_BE_32((hdr_p)->updater); \
+-     (hdr_p)->aspect_dx = LE_TO_BE_16((hdr_p)->aspect_dx); \
+-     (hdr_p)->aspect_dy = LE_TO_BE_16((hdr_p)->aspect_dy); \
+-     (hdr_p)->ext_flags = LE_TO_BE_16((hdr_p)->ext_flags); \
+-     (hdr_p)->keyframes = LE_TO_BE_16((hdr_p)->keyframes); \
+-     (hdr_p)->totalframes = LE_TO_BE_16((hdr_p)->totalframes); \
+-     (hdr_p)->req_memory = LE_TO_BE_32((hdr_p)->req_memory); \
+-     (hdr_p)->max_regions = LE_TO_BE_16((hdr_p)->max_regions); \
+-     (hdr_p)->transp_num = LE_TO_BE_16((hdr_p)->transp_num); \
+-     (hdr_p)->oframe1 = LE_TO_BE_32((hdr_p)->oframe1); \
+-     (hdr_p)->oframe2 = LE_TO_BE_32((hdr_p)->oframe2); \
+-    } while(0)
+-#else
+-
+-#define LE_TO_BE_16(i16) ((i16))
+-#define LE_TO_BE_32(i32) ((i32))
+-
+-#define FLX_FRAME_TYPE_FIX_ENDIANNESS(frm_type_p)
+-#define FLX_HUFFMAN_TABLE_FIX_ENDIANNESS(hffmn_table_p)
+-#define FLX_SEGMENT_TABLE_FIX_ENDIANNESS(sgmnt_table_p)
+-#define FLX_PREFIX_CHUNK_FIX_ENDIANNESS(prfx_chnk_p)
+-#define FLX_FRAME_CHUNK_FIX_ENDIANNESS(frm_chnk_p)
+-#define FLX_HDR_FIX_ENDIANNESS(hdr_p)
+-
+-#endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
+-
+ G_END_DECLS
+ 
+ #endif /* __GST_FLX_FMT_H__ */
+diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
+index a237976..aa1bed5 100644
+--- a/gst/flx/gstflxdec.c
++++ b/gst/flx/gstflxdec.c
+@@ -1,5 +1,6 @@
+ /* GStreamer
+  * Copyright (C) <1999> Erik Walthinsen <omega@temple-baptist.com>
++ * Copyright (C) <2016> Matthew Waters <matthew@centricular.com>
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Library General Public
+@@ -24,6 +25,7 @@
+ /*
+  * http://www.coolutils.com/Formats/FLI
+  * http://woodshole.er.usgs.gov/operations/modeling/flc.html
++ * http://www.compuphase.com/flic.htm
+  */
+ 
+ #ifdef HAVE_CONFIG_H
+@@ -73,10 +75,14 @@ static GstStateChangeReturn gst_flxdec_change_state (GstElement * element,
+ static gboolean gst_flxdec_src_query_handler (GstPad * pad, GstObject * parent,
+     GstQuery * query);
+ 
+-static void flx_decode_color (GstFlxDec *, guchar *, guchar *, gint);
+-static gboolean flx_decode_brun (GstFlxDec *, guchar *, guchar *);
+-static gboolean flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
+-static gboolean flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
++static gboolean flx_decode_color (GstFlxDec * flxdec, GstByteReader * reader,
++    GstByteWriter * writer, gint scale);
++static gboolean flx_decode_brun (GstFlxDec * flxdec,
++    GstByteReader * reader, GstByteWriter * writer);
++static gboolean flx_decode_delta_fli (GstFlxDec * flxdec,
++    GstByteReader * reader, GstByteWriter * writer);
++static gboolean flx_decode_delta_flc (GstFlxDec * flxdec,
++    GstByteReader * reader, GstByteWriter * writer);
+ 
+ #define rndalign(off) ((off) + ((off) & 1))
+ 
+@@ -204,57 +210,59 @@ gst_flxdec_sink_event_handler (GstPad * pad, GstObject * parent,
+ }
+ 
+ static gboolean
+-flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+-    guchar * dest)
++flx_decode_chunks (GstFlxDec * flxdec, gulong n_chunks, GstByteReader * reader,
++    GstByteWriter * writer)
+ {
+-  FlxFrameChunk *hdr;
+   gboolean ret = TRUE;
+ 
+-  g_return_val_if_fail (data != NULL, FALSE);
+-
+-  while (count--) {
+-    hdr = (FlxFrameChunk *) data;
+-    FLX_FRAME_CHUNK_FIX_ENDIANNESS (hdr);
+-    data += FlxFrameChunkSize;
++  while (n_chunks--) {
++    GstByteReader chunk;
++    guint32 size;
++    guint16 type;
++
++    if (!gst_byte_reader_get_uint32_le (reader, &size))
++      goto parse_error;
++    if (!gst_byte_reader_get_uint16_le (reader, &type))
++      goto parse_error;
++    GST_LOG_OBJECT (flxdec, "chunk has type 0x%02x size %d", type, size);
++
++    if (!gst_byte_reader_get_sub_reader (reader, &chunk,
++            size - FlxFrameChunkSize)) {
++      GST_ERROR_OBJECT (flxdec, "Incorrect size in the chunk header");
++      goto error;
++    }
+ 
+-    switch (hdr->id) {
++    switch (type) {
+       case FLX_COLOR64:
+-        flx_decode_color (flxdec, data, dest, 2);
+-        data += rndalign (hdr->size) - FlxFrameChunkSize;
++        ret = flx_decode_color (flxdec, &chunk, writer, 2);
+         break;
+ 
+       case FLX_COLOR256:
+-        flx_decode_color (flxdec, data, dest, 0);
+-        data += rndalign (hdr->size) - FlxFrameChunkSize;
++        ret = flx_decode_color (flxdec, &chunk, writer, 0);
+         break;
+ 
+       case FLX_BRUN:
+-        ret = flx_decode_brun (flxdec, data, dest);
+-        data += rndalign (hdr->size) - FlxFrameChunkSize;
++        ret = flx_decode_brun (flxdec, &chunk, writer);
+         break;
+ 
+       case FLX_LC:
+-        ret = flx_decode_delta_fli (flxdec, data, dest);
+-        data += rndalign (hdr->size) - FlxFrameChunkSize;
++        ret = flx_decode_delta_fli (flxdec, &chunk, writer);
+         break;
+ 
+       case FLX_SS2:
+-        ret = flx_decode_delta_flc (flxdec, data, dest);
+-        data += rndalign (hdr->size) - FlxFrameChunkSize;
++        ret = flx_decode_delta_flc (flxdec, &chunk, writer);
+         break;
+ 
+       case FLX_BLACK:
+-        memset (dest, 0, flxdec->size);
++        ret = gst_byte_writer_fill (writer, 0, flxdec->size);
+         break;
+ 
+       case FLX_MINI:
+-        data += rndalign (hdr->size) - FlxFrameChunkSize;
+         break;
+ 
+       default:
+-        GST_WARNING ("Unimplented chunk type: 0x%02x size: %d - skipping",
+-            hdr->id, hdr->size);
+-        data += rndalign (hdr->size) - FlxFrameChunkSize;
++        GST_WARNING ("Unimplemented chunk type: 0x%02x size: %d - skipping",
++            type, size);
+         break;
+     }
+ 
+@@ -263,43 +271,60 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+   }
+ 
+   return ret;
++
++parse_error:
++  GST_ERROR_OBJECT (flxdec, "Failed to decode chunk");
++error:
++  return FALSE;
+ }
+ 
+ 
+-static void
+-flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale)
++static gboolean
++flx_decode_color (GstFlxDec * flxdec, GstByteReader * reader,
++    GstByteWriter * writer, gint scale)
+ {
+-  guint packs, count, indx;
++  guint8 count, indx;
++  guint16 packs;
+ 
+-  g_return_if_fail (flxdec != NULL);
+-
+-  packs = (data[0] + (data[1] << 8));
+-
+-  data += 2;
++  if (!gst_byte_reader_get_uint16_le (reader, &packs))
++    goto error;
+   indx = 0;
+ 
+-  GST_LOG ("GstFlxDec: cmap packs: %d", packs);
++  GST_LOG ("GstFlxDec: cmap packs: %d", (guint) packs);
+   while (packs--) {
++    const guint8 *data;
++    guint16 actual_count;
++
+     /* color map index + skip count */
+-    indx += *data++;
++    if (!gst_byte_reader_get_uint8 (reader, &indx))
++      goto error;
+ 
+     /* number of rgb triplets */
+-    count = *data++ & 0xff;
+-    if (count == 0)
+-      count = 256;
++    if (!gst_byte_reader_get_uint8 (reader, &count))
++      goto error;
+ 
+-    GST_LOG ("GstFlxDec: cmap count: %d (indx: %d)", count, indx);
+-    flx_set_palette_vector (flxdec->converter, indx, count, data, scale);
++    actual_count = count == 0 ? 256 : count;
+ 
+-    data += (count * 3);
++    if (!gst_byte_reader_get_data (reader, count * 3, &data))
++      goto error;
++
++    GST_LOG_OBJECT (flxdec, "cmap count: %d (indx: %d)", actual_count, indx);
++    flx_set_palette_vector (flxdec->converter, indx, actual_count,
++        (guchar *) data, scale);
+   }
++
++  return TRUE;
++
++error:
++  GST_ERROR_OBJECT (flxdec, "Error decoding color palette");
++  return FALSE;
+ }
+ 
+ static gboolean
+-flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
++flx_decode_brun (GstFlxDec * flxdec, GstByteReader * reader,
++    GstByteWriter * writer)
+ {
+-  gulong count, lines, row;
+-  guchar x;
++  gulong lines, row;
+ 
+   g_return_val_if_fail (flxdec != NULL, FALSE);
+ 
+@@ -310,82 +335,125 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+      * contain more then 255 RLE packets. we use the frame 
+      * width instead. 
+      */
+-    data++;
++    if (!gst_byte_reader_skip (reader, 1))
++      goto error;
+ 
+     row = flxdec->hdr.width;
+     while (row) {
+-      count = *data++;
++      gint8 count;
++
++      if (!gst_byte_reader_get_int8 (reader, &count))
++        goto error;
++
++      if (count <= 0) {
++        const guint8 *data;
+ 
+-      if (count > 0x7f) {
+         /* literal run */
+-        count = 0x100 - count;
+-        if ((glong) row - (glong) count < 0) {
+-          GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
++        count = ABS (count);
++
++        GST_LOG_OBJECT (flxdec, "have literal run of size %d", count);
++
++        if (count > row) {
++          GST_ERROR_OBJECT (flxdec, "Invalid BRUN line detected. "
++              "bytes to write exceeds the end of the row");
+           return FALSE;
+         }
+         row -= count;
+ 
+-        while (count--)
+-          *dest++ = *data++;
+-
++        if (!gst_byte_reader_get_data (reader, count, &data))
++          goto error;
++        if (!gst_byte_writer_put_data (writer, data, count))
++          goto error;
+       } else {
+-        if ((glong) row - (glong) count < 0) {
+-          GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
++        guint8 x;
++
++        GST_LOG_OBJECT (flxdec, "have replicate run of size %d", count);
++
++        if (count > row) {
++          GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected."
++              "bytes to write exceeds the end of the row");
+           return FALSE;
+         }
+ 
+         /* replicate run */
+         row -= count;
+-        x = *data++;
+ 
+-        while (count--)
+-          *dest++ = x;
++        if (!gst_byte_reader_get_uint8 (reader, &x))
++          goto error;
++        if (!gst_byte_writer_fill (writer, x, count))
++          goto error;
+       }
+     }
+   }
+ 
+   return TRUE;
++
++error:
++  GST_ERROR_OBJECT (flxdec, "Failed to decode BRUN packet");
++  return FALSE;
+ }
+ 
+ static gboolean
+-flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
++flx_decode_delta_fli (GstFlxDec * flxdec, GstByteReader * reader,
++    GstByteWriter * writer)
+ {
+-  gulong count, packets, lines, start_line;
+-  guchar *start_p, x;
++  guint16 start_line, lines;
++  guint line_start_i;
+ 
+   g_return_val_if_fail (flxdec != NULL, FALSE);
+   g_return_val_if_fail (flxdec->delta_data != NULL, FALSE);
+ 
+   /* use last frame for delta */
+-  memcpy (dest, flxdec->delta_data, flxdec->size);
++  if (!gst_byte_writer_put_data (writer, flxdec->delta_data, flxdec->size))
++    goto error;
++
++  if (!gst_byte_reader_get_uint16_le (reader, &start_line))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &lines))
++    goto error;
++  GST_LOG_OBJECT (flxdec, "height %d start line %d line count %d",
++      flxdec->hdr.height, start_line, lines);
+ 
+-  start_line = (data[0] + (data[1] << 8));
+-  lines = (data[2] + (data[3] << 8));
+   if (start_line + lines > flxdec->hdr.height) {
+     GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. too many lines.");
+     return FALSE;
+   }
+-  data += 4;
+ 
+-  /* start position of delta */
+-  dest += (flxdec->hdr.width * start_line);
+-  start_p = dest;
++  line_start_i = flxdec->hdr.width * start_line;
++  if (!gst_byte_writer_set_pos (writer, line_start_i))
++    goto error;
+ 
+   while (lines--) {
++    guint8 packets;
++
+     /* packet count */
+-    packets = *data++;
++    if (!gst_byte_reader_get_uint8 (reader, &packets))
++      goto error;
++    GST_LOG_OBJECT (flxdec, "have %d packets", packets);
+ 
+     while (packets--) {
+       /* skip count */
+-      guchar skip = *data++;
+-      dest += skip;
++      guint8 skip;
++      gint8 count;
++      if (!gst_byte_reader_get_uint8 (reader, &skip))
++        goto error;
++
++      /* skip bytes */
++      if (!gst_byte_writer_set_pos (writer,
++              gst_byte_writer_get_pos (writer) + skip))
++        goto error;
+ 
+       /* RLE count */
+-      count = *data++;
++      if (!gst_byte_reader_get_int8 (reader, &count))
++        goto error;
++
++      if (count < 0) {
++        guint8 x;
+ 
+-      if (count > 0x7f) {
+         /* literal run */
+-        count = 0x100 - count;
++        count = ABS (count);
++        GST_LOG_OBJECT (flxdec, "have literal run of size %d at offset %d",
++            count, skip);
+ 
+         if (skip + count > flxdec->hdr.width) {
+           GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
+@@ -393,11 +461,16 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+           return FALSE;
+         }
+ 
+-        x = *data++;
+-        while (count--)
+-          *dest++ = x;
+-
++        if (!gst_byte_reader_get_uint8 (reader, &x))
++          goto error;
++        if (!gst_byte_writer_fill (writer, x, count))
++          goto error;
+       } else {
++        const guint8 *data;
++
++        GST_LOG_OBJECT (flxdec, "have replicate run of size %d at offset %d",
++            count, skip);
++
+         if (skip + count > flxdec->hdr.width) {
+           GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
+               "line too long.");
+@@ -405,45 +478,60 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+         }
+ 
+         /* replicate run */
+-        while (count--)
+-          *dest++ = *data++;
++        if (!gst_byte_reader_get_data (reader, count, &data))
++          goto error;
++        if (!gst_byte_writer_put_data (writer, data, count))
++          goto error;
+       }
+     }
+-    start_p += flxdec->hdr.width;
+-    dest = start_p;
++    line_start_i += flxdec->hdr.width;
++    if (!gst_byte_writer_set_pos (writer, line_start_i))
++      goto error;
+   }
+ 
+   return TRUE;
++
++error:
++  GST_ERROR_OBJECT (flxdec, "Failed to decode FLI packet");
++  return FALSE;
+ }
+ 
+ static gboolean
+-flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
++flx_decode_delta_flc (GstFlxDec * flxdec, GstByteReader * reader,
++    GstByteWriter * writer)
+ {
+-  gulong count, lines, start_l, opcode;
+-  guchar *start_p;
++  guint16 lines, start_l;
+ 
+   g_return_val_if_fail (flxdec != NULL, FALSE);
+   g_return_val_if_fail (flxdec->delta_data != NULL, FALSE);
+ 
+   /* use last frame for delta */
+-  memcpy (dest, flxdec->delta_data, flxdec->size);
++  if (!gst_byte_writer_put_data (writer, flxdec->delta_data, flxdec->size))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &lines))
++    goto error;
+ 
+-  lines = (data[0] + (data[1] << 8));
+   if (lines > flxdec->hdr.height) {
+     GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. too many lines.");
+     return FALSE;
+   }
+-  data += 2;
+ 
+-  start_p = dest;
+   start_l = lines;
+ 
+   while (lines) {
+-    dest = start_p + (flxdec->hdr.width * (start_l - lines));
++    guint16 opcode;
++
++    if (!gst_byte_writer_set_pos (writer,
++            flxdec->hdr.width * (start_l - lines)))
++      goto error;
+ 
+     /* process opcode(s) */
+-    while ((opcode = (data[0] + (data[1] << 8))) & 0xc000) {
+-      data += 2;
++    while (TRUE) {
++      if (!gst_byte_reader_get_uint16_le (reader, &opcode))
++        goto error;
++      if ((opcode & 0xc000) == 0)
++        break;
++
+       if ((opcode & 0xc000) == 0xc000) {
+         /* line skip count */
+         gulong skip = (0x10000 - opcode);
+@@ -453,27 +541,44 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+           return FALSE;
+         }
+         start_l += skip;
+-        dest += flxdec->hdr.width * skip;
++        if (!gst_byte_writer_set_pos (writer,
++                gst_byte_writer_get_pos (writer) + flxdec->hdr.width * skip))
++          goto error;
+       } else {
+         /* last pixel */
+-        dest += flxdec->hdr.width;
+-        *dest++ = (opcode & 0xff);
++        if (!gst_byte_writer_set_pos (writer,
++                gst_byte_writer_get_pos (writer) + flxdec->hdr.width))
++          goto error;
++        if (!gst_byte_writer_put_uint8 (writer, opcode & 0xff))
++          goto error;
+       }
+     }
+-    data += 2;
+ 
+     /* last opcode is the packet count */
++    GST_LOG_OBJECT (flxdec, "have %d packets", opcode);
+     while (opcode--) {
+       /* skip count */
+-      guchar skip = *data++;
+-      dest += skip;
++      guint8 skip;
++      gint8 count;
++
++      if (!gst_byte_reader_get_uint8 (reader, &skip))
++        goto error;
++      if (!gst_byte_writer_set_pos (writer,
++              gst_byte_writer_get_pos (writer) + skip))
++        goto error;
+ 
+       /* RLE count */
+-      count = *data++;
++      if (!gst_byte_reader_get_int8 (reader, &count))
++        goto error;
++
++      if (count < 0) {
++        guint16 x;
+ 
+-      if (count > 0x7f) {
+         /* replicate word run */
+-        count = 0x100 - count;
++        count = ABS (count);
++
++        GST_LOG_OBJECT (flxdec, "have replicate run of size %d at offset %d",
++            count, skip);
+ 
+         if (skip + count > flxdec->hdr.width) {
+           GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
+@@ -481,22 +586,31 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+           return FALSE;
+         }
+ 
++        if (!gst_byte_reader_get_uint16_le (reader, &x))
++          goto error;
++
+         while (count--) {
+-          *dest++ = data[0];
+-          *dest++ = data[1];
++          if (!gst_byte_writer_put_uint16_le (writer, x)) {
++            goto error;
++          }
+         }
+-        data += 2;
+       } else {
++        GST_LOG_OBJECT (flxdec, "have literal run of size %d at offset %d",
++            count, skip);
++
+         if (skip + count > flxdec->hdr.width) {
+           GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
+               "line too long.");
+           return FALSE;
+         }
+ 
+-        /* literal word run */
+         while (count--) {
+-          *dest++ = *data++;
+-          *dest++ = *data++;
++          guint16 x;
++
++          if (!gst_byte_reader_get_uint16_le (reader, &x))
++            goto error;
++          if (!gst_byte_writer_put_uint16_le (writer, x))
++            goto error;
+         }
+       }
+     }
+@@ -504,13 +618,91 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+   }
+ 
+   return TRUE;
++
++error:
++  GST_ERROR_OBJECT (flxdec, "Failed to decode FLI packet");
++  return FALSE;
++}
++
++static gboolean
++_read_flx_header (GstFlxDec * flxdec, GstByteReader * reader, FlxHeader * flxh)
++{
++  memset (flxh, 0, sizeof (*flxh));
++
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->size))
++    goto error;
++  if (flxh->size < FlxHeaderSize) {
++    GST_ERROR_OBJECT (flxdec, "Invalid file size in the header");
++    return FALSE;
++  }
++
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->type))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->frames))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->width))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->height))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->depth))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->flags))
++    goto error;
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->speed))
++    goto error;
++  if (!gst_byte_reader_skip (reader, 2))        /* reserved */
++    goto error;
++  /* FLC */
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->created))
++    goto error;
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->creator))
++    goto error;
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->updated))
++    goto error;
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->updater))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->aspect_dx))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->aspect_dy))
++    goto error;
++  /* EGI */
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->ext_flags))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->keyframes))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->totalframes))
++    goto error;
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->req_memory))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->max_regions))
++    goto error;
++  if (!gst_byte_reader_get_uint16_le (reader, &flxh->transp_num))
++    goto error;
++  if (!gst_byte_reader_skip (reader, 24))       /* reserved */
++    goto error;
++  /* FLC */
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->oframe1))
++    goto error;
++  if (!gst_byte_reader_get_uint32_le (reader, &flxh->oframe2))
++    goto error;
++  if (!gst_byte_reader_skip (reader, 40))       /* reserved */
++    goto error;
++
++  return TRUE;
++
++error:
++  GST_ERROR_OBJECT (flxdec, "Error reading file header");
++  return FALSE;
+ }
+ 
+ static GstFlowReturn
+ gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+ {
++  GstByteReader reader;
++  GstBuffer *input;
++  GstMapInfo map_info;
+   GstCaps *caps;
+-  guint avail;
++  guint available;
+   GstFlowReturn res = GST_FLOW_OK;
+ 
+   GstFlxDec *flxdec;
+@@ -521,31 +713,50 @@ gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+   g_return_val_if_fail (flxdec != NULL, GST_FLOW_ERROR);
+ 
+   gst_adapter_push (flxdec->adapter, buf);
+-  avail = gst_adapter_available (flxdec->adapter);
++  available = gst_adapter_available (flxdec->adapter);
++  input = gst_adapter_get_buffer (flxdec->adapter, available);
++  if (!gst_buffer_map (input, &map_info, GST_MAP_READ)) {
++    GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++        ("%s", "Failed to map buffer"), (NULL));
++    goto error;
++  }
++  gst_byte_reader_init (&reader, map_info.data, map_info.size);
+ 
+   if (flxdec->state == GST_FLXDEC_READ_HEADER) {
+-    if (avail >= FlxHeaderSize) {
+-      const guint8 *data = gst_adapter_map (flxdec->adapter, FlxHeaderSize);
++    if (available >= FlxHeaderSize) {
++      GstByteReader header;
+       GstCaps *templ;
+ 
+-      memcpy ((gchar *) & flxdec->hdr, data, FlxHeaderSize);
+-      FLX_HDR_FIX_ENDIANNESS (&(flxdec->hdr));
+-      gst_adapter_unmap (flxdec->adapter);
++      if (!gst_byte_reader_get_sub_reader (&reader, &header, FlxHeaderSize)) {
++        GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++            ("%s", "Could not read header"), (NULL));
++        goto unmap_input_error;
++      }
+       gst_adapter_flush (flxdec->adapter, FlxHeaderSize);
++      available -= FlxHeaderSize;
++
++      if (!_read_flx_header (flxdec, &header, &flxdec->hdr)) {
++        GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++            ("%s", "Failed to parse header"), (NULL));
++        goto unmap_input_error;
++      }
+ 
+       flxh = &flxdec->hdr;
+ 
+       /* check header */
+       if (flxh->type != FLX_MAGICHDR_FLI &&
+-          flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX)
+-        goto wrong_type;
++          flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX) {
++        GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
++            ("not a flx file (type %x)", flxh->type));
++        goto unmap_input_error;
++      }
+ 
+-      GST_LOG ("size      :  %d", flxh->size);
+-      GST_LOG ("frames    :  %d", flxh->frames);
+-      GST_LOG ("width     :  %d", flxh->width);
+-      GST_LOG ("height    :  %d", flxh->height);
+-      GST_LOG ("depth     :  %d", flxh->depth);
+-      GST_LOG ("speed     :  %d", flxh->speed);
++      GST_INFO_OBJECT (flxdec, "size      :  %d", flxh->size);
++      GST_INFO_OBJECT (flxdec, "frames    :  %d", flxh->frames);
++      GST_INFO_OBJECT (flxdec, "width     :  %d", flxh->width);
++      GST_INFO_OBJECT (flxdec, "height    :  %d", flxh->height);
++      GST_INFO_OBJECT (flxdec, "depth     :  %d", flxh->depth);
++      GST_INFO_OBJECT (flxdec, "speed     :  %d", flxh->speed);
+ 
+       flxdec->next_time = 0;
+ 
+@@ -573,18 +784,32 @@ gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+       gst_pad_set_caps (flxdec->srcpad, caps);
+       gst_caps_unref (caps);
+ 
+-      if (flxh->depth <= 8)
+-        flxdec->converter =
+-            flx_colorspace_converter_new (flxh->width, flxh->height);
++      /* zero means 8 */
++      if (flxh->depth == 0)
++        flxh->depth = 8;
++
++      if (flxh->depth != 8) {
++        GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE,
++            ("%s", "Don't know how to decode non 8 bit depth streams"), (NULL));
++        goto unmap_input_error;
++      }
++
++      flxdec->converter =
++          flx_colorspace_converter_new (flxh->width, flxh->height);
+ 
+       if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) {
+-        GST_LOG ("(FLC) aspect_dx :  %d", flxh->aspect_dx);
+-        GST_LOG ("(FLC) aspect_dy :  %d", flxh->aspect_dy);
+-        GST_LOG ("(FLC) oframe1   :  0x%08x", flxh->oframe1);
+-        GST_LOG ("(FLC) oframe2   :  0x%08x", flxh->oframe2);
++        GST_INFO_OBJECT (flxdec, "(FLC) aspect_dx :  %d", flxh->aspect_dx);
++        GST_INFO_OBJECT (flxdec, "(FLC) aspect_dy :  %d", flxh->aspect_dy);
++        GST_INFO_OBJECT (flxdec, "(FLC) oframe1   :  0x%08x", flxh->oframe1);
++        GST_INFO_OBJECT (flxdec, "(FLC) oframe2   :  0x%08x", flxh->oframe2);
+       }
+ 
+       flxdec->size = ((guint) flxh->width * (guint) flxh->height);
++      if (flxdec->size >= G_MAXSIZE / 4) {
++        GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++            ("%s", "Cannot allocate required memory"), (NULL));
++        goto unmap_input_error;
++      }
+ 
+       /* create delta and output frame */
+       flxdec->frame_data = g_malloc (flxdec->size);
+@@ -596,55 +821,66 @@ gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+     GstBuffer *out;
+ 
+     /* while we have enough data in the adapter */
+-    while (avail >= FlxFrameChunkSize && res == GST_FLOW_OK) {
+-      FlxFrameChunk flxfh;
+-      guchar *chunk;
+-      const guint8 *data;
+-      GstMapInfo map;
+-
+-      chunk = NULL;
+-      data = gst_adapter_map (flxdec->adapter, FlxFrameChunkSize);
+-      memcpy (&flxfh, data, FlxFrameChunkSize);
+-      FLX_FRAME_CHUNK_FIX_ENDIANNESS (&flxfh);
+-      gst_adapter_unmap (flxdec->adapter);
+-
+-      switch (flxfh.id) {
+-        case FLX_FRAME_TYPE:
+-          /* check if we have the complete frame */
+-          if (avail < flxfh.size)
+-            goto need_more_data;
+-
+-          /* flush header */
+-          gst_adapter_flush (flxdec->adapter, FlxFrameChunkSize);
+-
+-          chunk = gst_adapter_take (flxdec->adapter,
+-              flxfh.size - FlxFrameChunkSize);
+-          FLX_FRAME_TYPE_FIX_ENDIANNESS ((FlxFrameType *) chunk);
+-          if (((FlxFrameType *) chunk)->chunks == 0)
+-            break;
++    while (available >= FlxFrameChunkSize && res == GST_FLOW_OK) {
++      guint32 size;
++      guint16 type;
+ 
+-          /* create 32 bits output frame */
+-//          res = gst_pad_alloc_buffer_and_set_caps (flxdec->srcpad,
+-//              GST_BUFFER_OFFSET_NONE,
+-//              flxdec->size * 4, GST_PAD_CAPS (flxdec->srcpad), &out);
+-//          if (res != GST_FLOW_OK)
+-//            break;
++      if (!gst_byte_reader_get_uint32_le (&reader, &size))
++        goto parse_error;
++      if (available < size)
++        goto need_more_data;
+ 
+-          out = gst_buffer_new_and_alloc (flxdec->size * 4);
++      available -= size;
++      gst_adapter_flush (flxdec->adapter, size);
++
++      if (!gst_byte_reader_get_uint16_le (&reader, &type))
++        goto parse_error;
++
++      switch (type) {
++        case FLX_FRAME_TYPE:{
++          GstByteReader chunks;
++          GstByteWriter writer;
++          guint16 n_chunks;
++          GstMapInfo map;
++
++          GST_LOG_OBJECT (flxdec, "Have frame type 0x%02x of size %d", type,
++              size);
++
++          if (!gst_byte_reader_get_sub_reader (&reader, &chunks,
++                  size - FlxFrameChunkSize))
++            goto parse_error;
++
++          if (!gst_byte_reader_get_uint16_le (&chunks, &n_chunks))
++            goto parse_error;
++          GST_LOG_OBJECT (flxdec, "Have %d chunks", n_chunks);
++
++          if (n_chunks == 0)
++            break;
++          if (!gst_byte_reader_skip (&chunks, 8))       /* reserved */
++            goto parse_error;
++
++          gst_byte_writer_init_with_data (&writer, flxdec->frame_data,
++              flxdec->size, TRUE);
+ 
+           /* decode chunks */
+-          if (!flx_decode_chunks (flxdec,
+-                  ((FlxFrameType *) chunk)->chunks,
+-                  chunk + FlxFrameTypeSize, flxdec->frame_data)) {
++          if (!flx_decode_chunks (flxdec, n_chunks, &chunks, &writer)) {
+             GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
+                 ("%s", "Could not decode chunk"), NULL);
+-            return GST_FLOW_ERROR;
++            goto unmap_input_error;
+           }
++          gst_byte_writer_reset (&writer);
+ 
+           /* save copy of the current frame for possible delta. */
+           memcpy (flxdec->delta_data, flxdec->frame_data, flxdec->size);
+ 
+-          gst_buffer_map (out, &map, GST_MAP_WRITE);
++          out = gst_buffer_new_and_alloc (flxdec->size * 4);
++          if (!gst_buffer_map (out, &map, GST_MAP_WRITE)) {
++            GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++                ("%s", "Could not map output buffer"), NULL);
++            gst_buffer_unref (out);
++            goto unmap_input_error;
++          }
++
+           /* convert current frame. */
+           flx_colorspace_convert (flxdec->converter, flxdec->frame_data,
+               map.data);
+@@ -655,30 +891,32 @@ gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+ 
+           res = gst_pad_push (flxdec->srcpad, out);
+           break;
++        }
+         default:
+-          /* check if we have the complete frame */
+-          if (avail < flxfh.size)
+-            goto need_more_data;
+-
+-          gst_adapter_flush (flxdec->adapter, flxfh.size);
++          GST_DEBUG_OBJECT (flxdec, "Unknown frame type 0x%02x, skipping %d",
++              type, size);
++          if (!gst_byte_reader_skip (&reader, size - FlxFrameChunkSize))
++            goto parse_error;
+           break;
+       }
+-
+-      g_free (chunk);
+-
+-      avail = gst_adapter_available (flxdec->adapter);
+     }
+   }
++
++  gst_buffer_unmap (input, &map_info);
++  gst_buffer_unref (input);
++
+ need_more_data:
+   return res;
+ 
+   /* ERRORS */
+-wrong_type:
+-  {
+-    GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
+-        ("not a flx file (type %x)", flxh->type));
+-    return GST_FLOW_ERROR;
+-  }
++parse_error:
++  GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++      ("%s", "Failed to parse stream"), (NULL));
++unmap_input_error:
++  gst_buffer_unmap (input, &map_info);
++  gst_buffer_unref (input);
++error:
++  return GST_FLOW_ERROR;
+ }
+ 
+ static GstStateChangeReturn
+diff --git a/gst/flx/gstflxdec.h b/gst/flx/gstflxdec.h
+index 3f9a0aa..4fd8dfd 100644
+--- a/gst/flx/gstflxdec.h
++++ b/gst/flx/gstflxdec.h
+@@ -23,6 +23,8 @@
+ #include <gst/gst.h>
+ 
+ #include <gst/base/gstadapter.h>
++#include <gst/base/gstbytereader.h>
++#include <gst/base/gstbytewriter.h>
+ #include "flx_color.h"
+ 
+ G_BEGIN_DECLS
+@@ -45,7 +47,7 @@ struct _GstFlxDec {
+ 
+   guint8 *delta_data, *frame_data;
+   GstAdapter *adapter;
+-  gulong size;
++  gsize size;
+   GstFlxDecState state;
+   gint64 frame_time;
+   gint64 next_time;
+-- 
+2.10.2
+
diff --git a/gnu/packages/patches/gst-plugins-good-fix-invalid-read.patch b/gnu/packages/patches/gst-plugins-good-fix-invalid-read.patch
new file mode 100644
index 0000000000..1daaa2ae15
--- /dev/null
+++ b/gnu/packages/patches/gst-plugins-good-fix-invalid-read.patch
@@ -0,0 +1,37 @@
+Fixes upstream bug #774897 (flxdec: Unreferences itself one time too many on
+invalid files):
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774897
+
+Patch copied from upstream source repository:
+
+https://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=b31c504645a814c59d91d49e4fe218acaf93f4ca
+
+From b31c504645a814c59d91d49e4fe218acaf93f4ca Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
+Date: Wed, 23 Nov 2016 11:20:49 +0200
+Subject: [PATCH] flxdec: Don't unref() parent in the chain function
+
+We don't own the reference here, it is owned by the caller and given to
+us for the scope of this function. Leftover mistake from 0.10 porting.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774897
+---
+ gst/flx/gstflxdec.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
+index e675c99..a237976 100644
+--- a/gst/flx/gstflxdec.c
++++ b/gst/flx/gstflxdec.c
+@@ -677,7 +677,6 @@ wrong_type:
+   {
+     GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
+         ("not a flx file (type %x)", flxh->type));
+-    gst_object_unref (flxdec);
+     return GST_FLOW_ERROR;
+   }
+ }
+-- 
+2.10.2
+
diff --git a/gnu/packages/patches/gst-plugins-good-fix-signedness.patch b/gnu/packages/patches/gst-plugins-good-fix-signedness.patch
new file mode 100644
index 0000000000..a3e20e19dd
--- /dev/null
+++ b/gnu/packages/patches/gst-plugins-good-fix-signedness.patch
@@ -0,0 +1,58 @@
+This is a followup fix for upstream bug #774834 (flic decoder: Buffer overflow
+in flx_decode_delta_fli):
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774834#c2
+
+Patch copied from upstream source repository:
+
+https://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=1ab2b26193861b124426e2f8eb62b75b59ec5488
+
+From 1ab2b26193861b124426e2f8eb62b75b59ec5488 Mon Sep 17 00:00:00 2001
+From: Matthew Waters <matthew@centricular.com>
+Date: Tue, 22 Nov 2016 23:46:00 +1100
+Subject: [PATCH] flxdec: fix some warnings comparing unsigned < 0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+bf43f44fcfada5ec4a3ce60cb374340486fe9fac was comparing an unsigned
+expression to be < 0 which was always false.
+
+gstflxdec.c: In function ‘flx_decode_brun’:
+gstflxdec.c:322:33: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
+         if ((glong) row - count < 0) {
+                                 ^
+gstflxdec.c:332:33: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
+         if ((glong) row - count < 0) {
+                                 ^
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774834
+---
+ gst/flx/gstflxdec.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
+index d51a8e6..e675c99 100644
+--- a/gst/flx/gstflxdec.c
++++ b/gst/flx/gstflxdec.c
+@@ -319,7 +319,7 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+       if (count > 0x7f) {
+         /* literal run */
+         count = 0x100 - count;
+-        if ((glong) row - count < 0) {
++        if ((glong) row - (glong) count < 0) {
+           GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
+           return FALSE;
+         }
+@@ -329,7 +329,7 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+           *dest++ = *data++;
+ 
+       } else {
+-        if ((glong) row - count < 0) {
++        if ((glong) row - (glong) count < 0) {
+           GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
+           return FALSE;
+         }
+-- 
+2.10.2
+
diff --git a/gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch b/gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch
new file mode 100644
index 0000000000..f77dca2cd6
--- /dev/null
+++ b/gnu/packages/patches/gst-plugins-good-flic-bounds-check.patch
@@ -0,0 +1,319 @@
+Fix CVE-2016-{9634,9635,9636}.
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9634
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9635
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9636
+
+This fixes upstream bug #774834 (flic decoder: Buffer overflow in
+flx_decode_delta_fli):
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774834
+
+Patch copied from upstream source repository:
+
+https://cgit.freedesktop.org/gstreamer/gst-plugins-good/commit/?id=2e203a79b7d9af4029307c1a845b3c148d5f5e62
+
+From 2e203a79b7d9af4029307c1a845b3c148d5f5e62 Mon Sep 17 00:00:00 2001
+From: Matthew Waters <matthew@centricular.com>
+Date: Tue, 22 Nov 2016 19:05:00 +1100
+Subject: [PATCH] flxdec: add some write bounds checking
+
+Without checking the bounds of the frame we are writing into, we can
+write off the end of the destination buffer.
+
+https://scarybeastsecurity.blogspot.dk/2016/11/0day-exploit-advancing-exploitation.html
+
+https://bugzilla.gnome.org/show_bug.cgi?id=774834
+---
+ gst/flx/gstflxdec.c | 116 +++++++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 91 insertions(+), 25 deletions(-)
+
+diff --git a/gst/flx/gstflxdec.c b/gst/flx/gstflxdec.c
+index 604be2f..d51a8e6 100644
+--- a/gst/flx/gstflxdec.c
++++ b/gst/flx/gstflxdec.c
+@@ -74,9 +74,9 @@ static gboolean gst_flxdec_src_query_handler (GstPad * pad, GstObject * parent,
+     GstQuery * query);
+ 
+ static void flx_decode_color (GstFlxDec *, guchar *, guchar *, gint);
+-static void flx_decode_brun (GstFlxDec *, guchar *, guchar *);
+-static void flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
+-static void flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
++static gboolean flx_decode_brun (GstFlxDec *, guchar *, guchar *);
++static gboolean flx_decode_delta_fli (GstFlxDec *, guchar *, guchar *);
++static gboolean flx_decode_delta_flc (GstFlxDec *, guchar *, guchar *);
+ 
+ #define rndalign(off) ((off) + ((off) & 1))
+ 
+@@ -203,13 +203,14 @@ gst_flxdec_sink_event_handler (GstPad * pad, GstObject * parent,
+   return ret;
+ }
+ 
+-static void
++static gboolean
+ flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+     guchar * dest)
+ {
+   FlxFrameChunk *hdr;
++  gboolean ret = TRUE;
+ 
+-  g_return_if_fail (data != NULL);
++  g_return_val_if_fail (data != NULL, FALSE);
+ 
+   while (count--) {
+     hdr = (FlxFrameChunk *) data;
+@@ -228,17 +229,17 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+         break;
+ 
+       case FLX_BRUN:
+-        flx_decode_brun (flxdec, data, dest);
++        ret = flx_decode_brun (flxdec, data, dest);
+         data += rndalign (hdr->size) - FlxFrameChunkSize;
+         break;
+ 
+       case FLX_LC:
+-        flx_decode_delta_fli (flxdec, data, dest);
++        ret = flx_decode_delta_fli (flxdec, data, dest);
+         data += rndalign (hdr->size) - FlxFrameChunkSize;
+         break;
+ 
+       case FLX_SS2:
+-        flx_decode_delta_flc (flxdec, data, dest);
++        ret = flx_decode_delta_flc (flxdec, data, dest);
+         data += rndalign (hdr->size) - FlxFrameChunkSize;
+         break;
+ 
+@@ -256,7 +257,12 @@ flx_decode_chunks (GstFlxDec * flxdec, gulong count, guchar * data,
+         data += rndalign (hdr->size) - FlxFrameChunkSize;
+         break;
+     }
++
++    if (!ret)
++      break;
+   }
++
++  return ret;
+ }
+ 
+ 
+@@ -289,13 +295,13 @@ flx_decode_color (GstFlxDec * flxdec, guchar * data, guchar * dest, gint scale)
+   }
+ }
+ 
+-static void
++static gboolean
+ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ {
+   gulong count, lines, row;
+   guchar x;
+ 
+-  g_return_if_fail (flxdec != NULL);
++  g_return_val_if_fail (flxdec != NULL, FALSE);
+ 
+   lines = flxdec->hdr.height;
+   while (lines--) {
+@@ -313,12 +319,21 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+       if (count > 0x7f) {
+         /* literal run */
+         count = 0x100 - count;
++        if ((glong) row - count < 0) {
++          GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
++          return FALSE;
++        }
+         row -= count;
+ 
+         while (count--)
+           *dest++ = *data++;
+ 
+       } else {
++        if ((glong) row - count < 0) {
++          GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected.");
++          return FALSE;
++        }
++
+         /* replicate run */
+         row -= count;
+         x = *data++;
+@@ -328,22 +343,28 @@ flx_decode_brun (GstFlxDec * flxdec, guchar * data, guchar * dest)
+       }
+     }
+   }
++
++  return TRUE;
+ }
+ 
+-static void
++static gboolean
+ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ {
+   gulong count, packets, lines, start_line;
+   guchar *start_p, x;
+ 
+-  g_return_if_fail (flxdec != NULL);
+-  g_return_if_fail (flxdec->delta_data != NULL);
++  g_return_val_if_fail (flxdec != NULL, FALSE);
++  g_return_val_if_fail (flxdec->delta_data != NULL, FALSE);
+ 
+   /* use last frame for delta */
+   memcpy (dest, flxdec->delta_data, flxdec->size);
+ 
+   start_line = (data[0] + (data[1] << 8));
+   lines = (data[2] + (data[3] << 8));
++  if (start_line + lines > flxdec->hdr.height) {
++    GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. too many lines.");
++    return FALSE;
++  }
+   data += 4;
+ 
+   /* start position of delta */
+@@ -356,7 +377,8 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ 
+     while (packets--) {
+       /* skip count */
+-      dest += *data++;
++      guchar skip = *data++;
++      dest += skip;
+ 
+       /* RLE count */
+       count = *data++;
+@@ -364,12 +386,24 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+       if (count > 0x7f) {
+         /* literal run */
+         count = 0x100 - count;
+-        x = *data++;
+ 
++        if (skip + count > flxdec->hdr.width) {
++          GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
++              "line too long.");
++          return FALSE;
++        }
++
++        x = *data++;
+         while (count--)
+           *dest++ = x;
+ 
+       } else {
++        if (skip + count > flxdec->hdr.width) {
++          GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. "
++              "line too long.");
++          return FALSE;
++        }
++
+         /* replicate run */
+         while (count--)
+           *dest++ = *data++;
+@@ -378,21 +412,27 @@ flx_decode_delta_fli (GstFlxDec * flxdec, guchar * data, guchar * dest)
+     start_p += flxdec->hdr.width;
+     dest = start_p;
+   }
++
++  return TRUE;
+ }
+ 
+-static void
++static gboolean
+ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+ {
+   gulong count, lines, start_l, opcode;
+   guchar *start_p;
+ 
+-  g_return_if_fail (flxdec != NULL);
+-  g_return_if_fail (flxdec->delta_data != NULL);
++  g_return_val_if_fail (flxdec != NULL, FALSE);
++  g_return_val_if_fail (flxdec->delta_data != NULL, FALSE);
+ 
+   /* use last frame for delta */
+   memcpy (dest, flxdec->delta_data, flxdec->size);
+ 
+   lines = (data[0] + (data[1] << 8));
++  if (lines > flxdec->hdr.height) {
++    GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. too many lines.");
++    return FALSE;
++  }
+   data += 2;
+ 
+   start_p = dest;
+@@ -405,9 +445,15 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+     while ((opcode = (data[0] + (data[1] << 8))) & 0xc000) {
+       data += 2;
+       if ((opcode & 0xc000) == 0xc000) {
+-        /* skip count */
+-        start_l += (0x10000 - opcode);
+-        dest += flxdec->hdr.width * (0x10000 - opcode);
++        /* line skip count */
++        gulong skip = (0x10000 - opcode);
++        if (skip > flxdec->hdr.height) {
++          GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
++              "skip line count too big.");
++          return FALSE;
++        }
++        start_l += skip;
++        dest += flxdec->hdr.width * skip;
+       } else {
+         /* last pixel */
+         dest += flxdec->hdr.width;
+@@ -419,7 +465,8 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+     /* last opcode is the packet count */
+     while (opcode--) {
+       /* skip count */
+-      dest += *data++;
++      guchar skip = *data++;
++      dest += skip;
+ 
+       /* RLE count */
+       count = *data++;
+@@ -427,12 +474,25 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+       if (count > 0x7f) {
+         /* replicate word run */
+         count = 0x100 - count;
++
++        if (skip + count > flxdec->hdr.width) {
++          GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
++              "line too long.");
++          return FALSE;
++        }
++
+         while (count--) {
+           *dest++ = data[0];
+           *dest++ = data[1];
+         }
+         data += 2;
+       } else {
++        if (skip + count > flxdec->hdr.width) {
++          GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. "
++              "line too long.");
++          return FALSE;
++        }
++
+         /* literal word run */
+         while (count--) {
+           *dest++ = *data++;
+@@ -442,6 +502,8 @@ flx_decode_delta_flc (GstFlxDec * flxdec, guchar * data, guchar * dest)
+     }
+     lines--;
+   }
++
++  return TRUE;
+ }
+ 
+ static GstFlowReturn
+@@ -571,9 +633,13 @@ gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+           out = gst_buffer_new_and_alloc (flxdec->size * 4);
+ 
+           /* decode chunks */
+-          flx_decode_chunks (flxdec,
+-              ((FlxFrameType *) chunk)->chunks,
+-              chunk + FlxFrameTypeSize, flxdec->frame_data);
++          if (!flx_decode_chunks (flxdec,
++                  ((FlxFrameType *) chunk)->chunks,
++                  chunk + FlxFrameTypeSize, flxdec->frame_data)) {
++            GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
++                ("%s", "Could not decode chunk"), NULL);
++            return GST_FLOW_ERROR;
++          }
+ 
+           /* save copy of the current frame for possible delta. */
+           memcpy (flxdec->delta_data, flxdec->frame_data, flxdec->size);
+-- 
+2.10.2
+
diff --git a/gnu/packages/patches/ldc-disable-tests.patch b/gnu/packages/patches/ldc-disable-tests.patch
index 3f5e6c29a1..bdd6e5b76c 100644
--- a/gnu/packages/patches/ldc-disable-tests.patch
+++ b/gnu/packages/patches/ldc-disable-tests.patch
@@ -4,19 +4,9 @@ two others use networking.  Not bad out of almost 700 tests!
 
 by Pjotr Prins <pjotr.guix@thebird.nl>
 
-diff --git a/std/datetime.d b/std/datetime.d
-index 8e4ed3b..6c15bc5 100644
---- a/std/datetime.d
-+++ b/std/datetime.d
-@@ -28018,6 +28018,7 @@ public:
-             The default directory where the TZ Database files are. It's empty
-             for Windows, since Windows doesn't have them.
-           +/
-+          
-         enum defaultTZDatabaseDir = "/usr/share/zoneinfo/";
-     }
-     else version(Windows)
-@@ -28069,14 +28070,13 @@ assert(tz.dstName == "PDT");
+--- a/std/datetime.d.orig	2016-11-24 01:13:52.584495545 +0100
++++ b/std/datetime.d	2016-11-24 01:17:09.655306728 +0100
+@@ -28081,22 +28081,24 @@
          import std.range : retro;
          import std.format : format;
  
@@ -25,9 +15,20 @@ index 8e4ed3b..6c15bc5 100644
          enforce(tzDatabaseDir.exists(), new DateTimeException(format("Directory %s does not exist.", tzDatabaseDir)));
          enforce(tzDatabaseDir.isDir, new DateTimeException(format("%s is not a directory.", tzDatabaseDir)));
  
--        immutable file = buildNormalizedPath(tzDatabaseDir, name);
-+        auto filename = "./" ~ strip(name); // make sure the prefix is not stripped
-+        immutable file = buildNormalizedPath(tzDatabaseDir, filename);
+         version(Android)
+         {
++            name = strip(name);
+             auto tzfileOffset = name in tzdataIndex(tzDatabaseDir);
+             enforce(tzfileOffset, new DateTimeException(format("The time zone %s is not listed.", name)));
+             string tzFilename = separate_index ? "zoneinfo.dat" : "tzdata";
+             immutable file = buildNormalizedPath(tzDatabaseDir, tzFilename);
+         }
+         else
+-            immutable file = buildNormalizedPath(tzDatabaseDir, name);
++        {
++            auto filename = "./" ~ strip(name); // make sure the prefix is not stripped
++            immutable file = buildNormalizedPath(tzDatabaseDir, filename);
++        }
  
 -        enforce(file.exists(), new DateTimeException(format("File %s does not exist.", file)));
 +        enforce(file.exists(), new DateTimeException(format("File %s does not exist in %s.", file, tzDatabaseDir)));
@@ -54,23 +55,6 @@ diff --git a/std/socket.d b/std/socket.d
 index b85d1c9..7fbf346 100644
 --- a/std/socket.d
 +++ b/std/socket.d
-@@ -517,6 +517,8 @@ class Protocol
- 
- unittest
- {
-+    pragma(msg, "test disabled on GNU Guix");
-+/*
-     // getprotobyname,number are unimplemented on Android
-     softUnittest({
-         Protocol proto = new Protocol;
-@@ -530,6 +532,7 @@ unittest
-         assert(proto.name == "tcp");
-         assert(proto.aliases.length == 1 && proto.aliases[0] == "TCP");
-     });
-+*/
- }
- 
- 
 @@ -859,6 +862,8 @@ class InternetHost
  
  unittest
diff --git a/gnu/packages/patches/python-2.7-site-prefixes.patch b/gnu/packages/patches/python-2.7-site-prefixes.patch
new file mode 100644
index 0000000000..9e3066508f
--- /dev/null
+++ b/gnu/packages/patches/python-2.7-site-prefixes.patch
@@ -0,0 +1,26 @@
+Add all /gnu/store/ prefixes found in PYTHONPATH to the prefixes where
+site-packages (and .pth files) are searched.
+
+*** Python-2.7.11/Lib/site.py.orig	2016-10-17 23:27:23.746149690 +0200
+--- Python-2.7.11/Lib/site.py	2016-10-17 23:44:51.930871644 +0200
+***************
+*** 65,70 ****
+--- 65,82 ----
+  
+  # Prefixes for site-packages; add additional prefixes like /usr/local here
+  PREFIXES = [sys.prefix, sys.exec_prefix]
++ # Guix: Add all /gnu/store-paths in PYTHONPATH--these are all
++ # "prefixes".  This is required to search .pth files in all python
++ # packages contained in /gnu/store which is required to make
++ # .pth-defined namespace packages work.
++ # This is necessary if the packages are not merged into a single
++ # `site-packages` directory (like when using `guix environment`) but
++ # listed in PYTHONPATH (like when running `guix build`).
++ for p in sys.path:
++     if p.startswith('/gnu/store/'):
++         PREFIXES.append(p[:p.find('/', 44)]) # find first pathsep after hash
++ del p
++ 
+  # Enable per user site-packages directory
+  # set it to False to disable the feature or True to force the feature
+  ENABLE_USER_SITE = None
diff --git a/gnu/packages/patches/python-rarfile-fix-tests.patch b/gnu/packages/patches/python-rarfile-fix-tests.patch
deleted file mode 100644
index 8ae8894009..0000000000
--- a/gnu/packages/patches/python-rarfile-fix-tests.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-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__