File gstreamer-CVE-2022-1922-matroska.patch of Package gstreamer-0_10-plugins-good.25653
diff -urp gst-plugins-good-0.10.31.orig/gst/matroska/matroska-read-common.c gst-plugins-good-0.10.31/gst/matroska/matroska-read-common.c
--- gst-plugins-good-0.10.31.orig/gst/matroska/matroska-read-common.c 2012-01-18 04:02:02.000000000 -0600
+++ gst-plugins-good-0.10.31/gst/matroska/matroska-read-common.c 2022-08-22 11:59:37.355954655 -0500
@@ -56,25 +56,34 @@ GST_DEBUG_CATEGORY (matroskareadcommon_d
GST_DEBUG_OBJECT (common, "Parsing " element " element " \
" finished with '%s'", gst_flow_get_name (ret))
+/* 120MB as maximum decompressed data size. Anything bigger is likely
+ * pathological, and like this we avoid out of memory situations in many cases
+ */
+#define MAX_DECOMPRESS_SIZE (120 * 1024 * 1024)
+
static gboolean
gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
guint8 ** data_out, guint * size_out,
GstMatroskaTrackCompressionAlgorithm algo)
{
guint8 *new_data = NULL;
- guint new_size = 0;
+ gsize new_size = 0;
guint8 *data = *data_out;
- guint size = *size_out;
+ const gsize size = *size_out;
gboolean ret = TRUE;
+ if (size > G_MAXUINT32) {
+ GST_WARNING ("too large compressed data buffer.");
+ ret = FALSE;
+ goto out;
+ }
+
if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_ZLIB) {
#ifdef HAVE_ZLIB
/* zlib encoded data */
z_stream zstream;
- guint orig_size;
int result;
- orig_size = size;
zstream.zalloc = (alloc_func) 0;
zstream.zfree = (free_func) 0;
zstream.opaque = (voidpf) 0;
@@ -84,8 +93,8 @@ gst_matroska_decompress_data (GstMatrosk
goto out;
}
zstream.next_in = (Bytef *) data;
- zstream.avail_in = orig_size;
- new_size = orig_size;
+ zstream.avail_in = size;
+ new_size = size;
new_data = g_malloc (new_size);
zstream.avail_out = new_size;
zstream.next_out = (Bytef *) new_data;
@@ -98,10 +107,18 @@ gst_matroska_decompress_data (GstMatrosk
inflateEnd (&zstream);
break;
}
+ if (new_size > G_MAXSIZE - 4000 || new_size + 4000 > MAX_DECOMPRESS_SIZE) {
+ GST_WARNING ("too big decompressed data");
+ result = Z_MEM_ERROR;
+ break;
+ }
+
new_size += 4000;
new_data = g_realloc (new_data, new_size);
zstream.next_out = (Bytef *) (new_data + zstream.total_out);
- zstream.avail_out += 4000;
+ /* avail_out is an unsigned int */
+ g_assert (new_size - zstream.total_out <= G_MAXUINT);
+ zstream.avail_out = new_size - zstream.total_out;
} while (zstream.avail_in != 0 && result != Z_STREAM_END);
if (result != Z_STREAM_END) {
@@ -120,13 +137,11 @@ gst_matroska_decompress_data (GstMatrosk
#ifdef HAVE_BZ2
/* bzip2 encoded data */
bz_stream bzstream;
- guint orig_size;
int result;
bzstream.bzalloc = NULL;
bzstream.bzfree = NULL;
bzstream.opaque = NULL;
- orig_size = size;
if (BZ2_bzDecompressInit (&bzstream, 0, 0) != BZ_OK) {
GST_WARNING ("bzip2 initialization failed.");
@@ -135,8 +150,8 @@ gst_matroska_decompress_data (GstMatrosk
}
bzstream.next_in = (char *) data;
- bzstream.avail_in = orig_size;
- new_size = orig_size;
+ bzstream.avail_in = size;
+ new_size = size;
new_data = g_malloc (new_size);
bzstream.avail_out = new_size;
bzstream.next_out = (char *) new_data;
@@ -149,17 +164,31 @@ gst_matroska_decompress_data (GstMatrosk
BZ2_bzDecompressEnd (&bzstream);
break;
}
+ if (new_size > G_MAXSIZE - 4000 || new_size + 4000 > MAX_DECOMPRESS_SIZE) {
+ GST_WARNING ("too big decompressed data");
+ result = BZ_MEM_ERROR;
+ break;
+ }
+
new_size += 4000;
new_data = g_realloc (new_data, new_size);
- bzstream.next_out = (char *) (new_data + bzstream.total_out_lo32);
- bzstream.avail_out += 4000;
+ bzstream.next_out =
+ (char *) (new_data + ((guint64) bzstream.total_out_hi32 << 32) +
+ bzstream.total_out_lo32);
+ /* avail_out is an unsigned int */
+ g_assert (new_size - ((guint64) bzstream.total_out_hi32 << 32) +
+ bzstream.total_out_lo32 <= G_MAXUINT);
+ bzstream.avail_out =
+ new_size - ((guint64) bzstream.total_out_hi32 << 32) +
+ bzstream.total_out_lo32;
} while (bzstream.avail_in != 0 && result != BZ_STREAM_END);
if (result != BZ_STREAM_END) {
ret = FALSE;
goto out;
} else {
- new_size = bzstream.total_out_lo32;
+ new_size =
+ ((guint64) bzstream.total_out_hi32 << 32) + bzstream.total_out_lo32;
BZ2_bzDecompressEnd (&bzstream);
}
#else
@@ -170,7 +199,13 @@ gst_matroska_decompress_data (GstMatrosk
} else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_LZO1X) {
/* lzo encoded data */
int result;
- int orig_size, out_size;
+ gint orig_size, out_size;
+
+ if (size > G_MAXINT) {
+ GST_WARNING ("too large compressed data buffer.");
+ ret = FALSE;
+ goto out;
+ }
orig_size = size;
out_size = size;
@@ -184,6 +219,11 @@ gst_matroska_decompress_data (GstMatrosk
result = lzo1x_decode (new_data, &out_size, data, &orig_size);
if (orig_size > 0) {
+ if (new_size > G_MAXINT - 4000 || new_size + 4000 > MAX_DECOMPRESS_SIZE) {
+ GST_WARNING ("too big decompressed data");
+ result = LZO_ERROR;
+ break;
+ }
new_size += 4000;
new_data = g_realloc (new_data, new_size);
}
@@ -202,6 +242,13 @@ gst_matroska_decompress_data (GstMatrosk
} else if (algo == GST_MATROSKA_TRACK_COMPRESSION_ALGORITHM_HEADERSTRIP) {
/* header stripped encoded data */
if (enc->comp_settings_length > 0) {
+ if (size > G_MAXSIZE - enc->comp_settings_length
+ || size + enc->comp_settings_length > MAX_DECOMPRESS_SIZE) {
+ GST_WARNING ("too big decompressed data");
+ ret = FALSE;
+ goto out;
+ }
+
new_data = g_malloc (size + enc->comp_settings_length);
new_size = size + enc->comp_settings_length;