summaryrefslogtreecommitdiffstats
path: root/meta/recipes-multimedia/flac/files/CVE-2020-22219.patch
blob: e042872dc0e18af8af12faadc4735e5353bfc37b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
From 579ff6922089cbbbd179619e40e622e279bd719f Mon Sep 17 00:00:00 2001
From: Martijn van Beurden <mvanb1@gmail.com>
Date: Wed, 3 Aug 2022 13:52:19 +0200
Subject: [PATCH] flac: Add and use _nofree variants of safe_realloc functions

Parts of the code use realloc like

x = safe_realloc(x, somesize);

when this is the case, the safe_realloc variant used must free the
old memory block in case it fails, otherwise it will leak. However,
there are also instances in the code where handling is different:

if (0 == (x = safe_realloc(y, somesize)))
    return false

in this case, y should not be freed, as y is not set to NULL we
could encounter double frees. Here the safe_realloc_nofree
functions are used.

Upstream-Status: Backport [https://github.com/xiph/flac/commit/21fe95ee828b0b9b944f6aa0bb02d24fbb981815]
CVE: CVE-2020-22219

Signed-off-by: Meenali Gupta <meenali.gupta@windriver.com>
---
 include/share/alloc.h         | 41 +++++++++++++++++++++++++++++++----
 src/flac/encode.c             |  4 ++--
 src/flac/foreign_metadata.c   |  2 +-
 src/libFLAC/bitwriter.c       |  2 +-
 src/libFLAC/metadata_object.c |  2 +-
 src/plugin_common/tags.c      |  2 +-
 src/share/utf8/iconvert.c     |  2 +-
 7 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/include/share/alloc.h b/include/share/alloc.h
index 914de9b..55bdd1d 100644
--- a/include/share/alloc.h
+++ b/include/share/alloc.h
@@ -161,17 +161,30 @@ static inline void *safe_realloc_(void *ptr, size_t size)
		free(oldptr);
	return newptr;
 }
-static inline void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2)
+static inline void *safe_realloc_nofree_add_2op_(void *ptr, size_t size1, size_t size2)
+{
+	size2 += size1;
+	if(size2 < size1)
+		return 0;
+	return realloc(ptr, size2);
+}
+
+static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3)
 {
	size2 += size1;
	if(size2 < size1) {
		free(ptr);
		return 0;
	}
-	return realloc(ptr, size2);
+	size3 += size2;
+	if(size3 < size2) {
+		free(ptr);
+		return 0;
+	}
+	return safe_realloc_(ptr, size3);
 }

-static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3)
+static inline void *safe_realloc_nofree_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3)
 {
	size2 += size1;
	if(size2 < size1)
@@ -182,7 +195,7 @@ static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2,
	return realloc(ptr, size3);
 }

-static inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4)
+static inline void *safe_realloc_nofree_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4)
 {
	size2 += size1;
	if(size2 < size1)
@@ -205,6 +218,15 @@ static inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2)
	return safe_realloc_(ptr, size1*size2);
 }

+static inline void *safe_realloc_nofree_mul_2op_(void *ptr, size_t size1, size_t size2)
+{
+	if(!size1 || !size2)
+		return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
+	if(size1 > SIZE_MAX / size2)
+		return 0;
+	return realloc(ptr, size1*size2);
+}
+
 /* size1 * (size2 + size3) */
 static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3)
 {
@@ -216,4 +238,15 @@ static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2,
	return safe_realloc_mul_2op_(ptr, size1, size2);
 }

+/* size1 * (size2 + size3) */
+static inline void *safe_realloc_nofree_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3)
+{
+	if(!size1 || (!size2 && !size3))
+		return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
+	size2 += size3;
+	if(size2 < size3)
+		return 0;
+	return safe_realloc_nofree_mul_2op_(ptr, size1, size2);
+}
+
 #endif
diff --git a/src/flac/encode.c b/src/flac/encode.c
index a9b907f..f87250c 100644
--- a/src/flac/encode.c
+++ b/src/flac/encode.c
@@ -1743,10 +1743,10 @@ static void static_metadata_clear(static_metadata_t *m)
 static FLAC__bool static_metadata_append(static_metadata_t *m, FLAC__StreamMetadata *d, FLAC__bool needs_delete)
 {
	void *x;
-	if(0 == (x = safe_realloc_muladd2_(m->metadata, sizeof(*m->metadata), /*times (*/m->num_metadata, /*+*/1/*)*/)))
+	if(0 == (x = safe_realloc_nofree_muladd2_(m->metadata, sizeof(*m->metadata), /*times (*/m->num_metadata, /*+*/1/*)*/)))
		return false;
	m->metadata = (FLAC__StreamMetadata**)x;
-	if(0 == (x = safe_realloc_muladd2_(m->needs_delete, sizeof(*m->needs_delete), /*times (*/m->num_metadata, /*+*/1/*)*/)))
+	if(0 == (x = safe_realloc_nofree_muladd2_(m->needs_delete, sizeof(*m->needs_delete), /*times (*/m->num_metadata, /*+*/1/*)*/)))
		return false;
	m->needs_delete = (FLAC__bool*)x;
	m->metadata[m->num_metadata] = d;
diff --git a/src/flac/foreign_metadata.c b/src/flac/foreign_metadata.c
index 9ad9c18..fdfb3cf 100644
--- a/src/flac/foreign_metadata.c
+++ b/src/flac/foreign_metadata.c
@@ -75,7 +75,7 @@ static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **er

 static FLAC__bool append_block_(foreign_metadata_t *fm, FLAC__off_t offset, FLAC__uint32 size, const char **error)
 {
-	foreign_block_t *fb = safe_realloc_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/);
+	foreign_block_t *fb = safe_realloc_nofree_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/);
	if(fb) {
		fb[fm->num_blocks].offset = offset;
		fb[fm->num_blocks].size = size;
diff --git a/src/libFLAC/bitwriter.c b/src/libFLAC/bitwriter.c
index 6e86585..a510b0d 100644
--- a/src/libFLAC/bitwriter.c
+++ b/src/libFLAC/bitwriter.c
@@ -124,7 +124,7 @@ FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, uint32_t bits_to_add)
	FLAC__ASSERT(new_capacity > bw->capacity);
	FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD));

-	new_buffer = safe_realloc_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity);
+	new_buffer = safe_realloc_nofree_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity);
	if(new_buffer == 0)
		return false;
	bw->buffer = new_buffer;
diff --git a/src/libFLAC/metadata_object.c b/src/libFLAC/metadata_object.c
index de8e513..aef65be 100644
--- a/src/libFLAC/metadata_object.c
+++ b/src/libFLAC/metadata_object.c
@@ -98,7 +98,7 @@ static FLAC__bool free_copy_bytes_(FLAC__byte **to, const FLAC__byte *from, uint
 /* realloc() failure leaves entry unchanged */
 static FLAC__bool ensure_null_terminated_(FLAC__byte **entry, uint32_t length)
 {
-	FLAC__byte *x = safe_realloc_add_2op_(*entry, length, /*+*/1);
+	FLAC__byte *x = safe_realloc_nofree_add_2op_(*entry, length, /*+*/1);
	if (x != NULL) {
		x[length] = '\0';
		*entry = x;
diff --git a/src/plugin_common/tags.c b/src/plugin_common/tags.c
index ae440c5..dfa10d3 100644
--- a/src/plugin_common/tags.c
+++ b/src/plugin_common/tags.c
@@ -317,7 +317,7 @@ FLAC__bool FLAC_plugin__tags_add_tag_utf8(FLAC__StreamMetadata *tags, const char
		const size_t value_len = strlen(value);
		const size_t separator_len = strlen(separator);
		FLAC__byte *new_entry;
-		if(0 == (new_entry = safe_realloc_add_4op_(entry->entry, entry->length, /*+*/value_len, /*+*/separator_len, /*+*/1)))
+		if(0 == (new_entry = safe_realloc_nofree_add_4op_(entry->entry, entry->length, /*+*/value_len, /*+*/separator_len, /*+*/1)))
			return false;
		memcpy(new_entry+entry->length, separator, separator_len);
		entry->length += separator_len;
diff --git a/src/share/utf8/iconvert.c b/src/share/utf8/iconvert.c
index 8ab53c1..876c06e 100644
--- a/src/share/utf8/iconvert.c
+++ b/src/share/utf8/iconvert.c
@@ -149,7 +149,7 @@ int iconvert(const char *fromcode, const char *tocode,
       iconv_close(cd1);
       return ret;
     }
-    newbuf = safe_realloc_add_2op_(utfbuf, (ob - utfbuf), /*+*/1);
+    newbuf = safe_realloc_nofree_add_2op_(utfbuf, (ob - utfbuf), /*+*/1);
     if (!newbuf)
       goto fail;
     ob = (ob - utfbuf) + newbuf;
--
2.40.0