fix CVE-2020-22219

signed-off-by chenhaixiang3@huawei.com
This commit is contained in:
chenhaixiang 2023-08-28 22:11:00 -04:00
parent b3a95f8efa
commit cbc2db2634
4 changed files with 372 additions and 1 deletions

View File

@ -0,0 +1,41 @@
From b715d7b9fe90f5b411ae1c159553c7c287f0789a Mon Sep 17 00:00:00 2001
From: lutianxiong <lutianxiong@huawei.com>
Date: Thu, 4 Jun 2020 14:58:06 +0800
Subject: [PATCH] fix potential memleak
Reference:https://github.com/xiph/flac/commit/b715d7b9fe90f5b411ae1c159553c7c287f0789a
---
include/share/alloc.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/include/share/alloc.h b/include/share/alloc.h
index edd3a79e..9b53b010 100644
--- a/include/share/alloc.h
+++ b/include/share/alloc.h
@@ -200,8 +200,10 @@ static inline void *safe_realloc_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)
+ if(size1 > SIZE_MAX / size2) {
+ free(ptr);
return 0;
+ }
return safe_realloc_(ptr, size1*size2);
}
@@ -211,8 +213,10 @@ static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2,
if(!size1 || (!size2 && !size3))
return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
size2 += size3;
- if(size2 < size3)
+ if(size2 < size3) {
+ free(ptr);
return 0;
+ }
return safe_realloc_mul_2op_(ptr, size1, size2);
}
--
2.27.0

View File

@ -0,0 +1,195 @@
From 21fe95ee828b0b9b944f6aa0bb02d24fbb981815 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] 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.
Reference:https://github.com/xiph/flac/commit/21fe95ee828b0b9b944f6aa0bb02d24fbb981815
---
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 9b53b010..74f444d6 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)
@@ -207,6 +220,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)
{
@@ -220,4 +242,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 a7d1f7b2..b82ced76 100644
--- a/src/flac/encode.c
+++ b/src/flac/encode.c
@@ -1734,10 +1734,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 9a1fb96c..c86dff42 100644
--- a/src/flac/foreign_metadata.c
+++ b/src/flac/foreign_metadata.c
@@ -74,7 +74,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 79ab8649..8865a2f4 100644
--- a/src/libFLAC/bitwriter.c
+++ b/src/libFLAC/bitwriter.c
@@ -133,7 +133,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 7cc8ee9f..2c7da8db 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 e9227444..ffd846b6 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 8ab53c10..876c06e8 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.27.0

View File

@ -0,0 +1,129 @@
From 707dace4bd82cd6042e524c72544ab50de223a10 Mon Sep 17 00:00:00 2001
From: Martijn van Beurden <mvanb1@gmail.com>
Date: Wed, 3 Aug 2022 19:23:46 +0200
Subject: [PATCH] Leave metadata items untouched if resize function fails
Conflict: delete the comment from the include/FLAC/all.h file.
Reference: https://github.com/xiph/flac/commit/707dace4bd82cd6042e524c72544ab50de223a10
---
include/FLAC/metadata.h | 12 ++++++++----
src/libFLAC/metadata_object.c | 36 ++++++++++++++++++++++++-----------
2 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/include/FLAC/metadata.h b/include/FLAC/metadata.h
index aa369054..bf1bffe4 100644
--- a/include/FLAC/metadata.h
+++ b/include/FLAC/metadata.h
@@ -1398,7 +1398,8 @@ FLAC_API FLAC__bool FLAC__metadata_object_application_set_data(FLAC__StreamMetad
/** Resize the seekpoint array.
*
* If the size shrinks, elements will truncated; if it grows, new placeholder
- * points will be added to the end.
+ * points will be added to the end. If this function returns false, the
+ * object is left untouched.
*
* \param object A pointer to an existing SEEKTABLE object.
* \param new_num_points The desired length of the array; may be \c 0.
@@ -1611,7 +1612,8 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_set_vendor_string(FLAC__
/** Resize the comment array.
*
* If the size shrinks, elements will truncated; if it grows, new empty
- * fields will be added to the end.
+ * fields will be added to the end. If this function returns false, the
+ * object is left untouched.
*
* \param object A pointer to an existing VORBIS_COMMENT object.
* \param new_num_comments The desired length of the array; may be \c 0.
@@ -1891,7 +1893,8 @@ FLAC_API void FLAC__metadata_object_cuesheet_track_delete(FLAC__StreamMetadata_C
/** Resize a track's index point array.
*
* If the size shrinks, elements will truncated; if it grows, new blank
- * indices will be added to the end.
+ * indices will be added to the end. If this function returns false, the
+ * track object is left untouched.
*
* \param object A pointer to an existing CUESHEET object.
* \param track_num The index of the track to modify. NOTE: this is not
@@ -1977,7 +1980,8 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_delete_index(FLAC__Stre
/** Resize the track array.
*
* If the size shrinks, elements will truncated; if it grows, new blank
- * tracks will be added to the end.
+ * tracks will be added to the end. If this function returns false, the
+ * object is left untouched.
*
* \param object A pointer to an existing CUESHEET object.
* \param new_num_tracks The desired length of the array; may be \c 0.
diff --git a/src/libFLAC/metadata_object.c b/src/libFLAC/metadata_object.c
index 2c7da8db..d6ac3fc5 100644
--- a/src/libFLAC/metadata_object.c
+++ b/src/libFLAC/metadata_object.c
@@ -952,8 +952,13 @@ FLAC_API FLAC__bool FLAC__metadata_object_seektable_resize_points(FLAC__StreamMe
free(object->data.seek_table.points);
object->data.seek_table.points = 0;
}
- else if ((object->data.seek_table.points = safe_realloc_(object->data.seek_table.points, new_size)) == NULL)
- return false;
+ else {
+ /* Leave object->data.seek_table.points untouched if realloc fails */
+ FLAC__StreamMetadata_SeekPoint *tmpptr;
+ if ((tmpptr = realloc(object->data.seek_table.points, new_size)) == NULL)
+ return false;
+ object->data.seek_table.points = tmpptr;
+ }
/* if growing, set new elements to placeholders */
if (new_size > old_size) {
@@ -1207,12 +1212,11 @@ FLAC_API FLAC__bool FLAC__metadata_object_vorbiscomment_resize_comments(FLAC__St
object->data.vorbis_comment.comments = 0;
}
else {
- FLAC__StreamMetadata_VorbisComment_Entry *oldptr = object->data.vorbis_comment.comments;
- if ((object->data.vorbis_comment.comments = realloc(object->data.vorbis_comment.comments, new_size)) == NULL) {
- vorbiscomment_entry_array_delete_(oldptr, object->data.vorbis_comment.num_comments);
- object->data.vorbis_comment.num_comments = 0;
+ /* Leave object->data.vorbis_comment.comments untouched if realloc fails */
+ FLAC__StreamMetadata_VorbisComment_Entry *tmpptr;
+ if ((tmpptr = realloc(object->data.vorbis_comment.comments, new_size)) == NULL)
return false;
- }
+ object->data.vorbis_comment.comments = tmpptr;
}
/* if growing, zero all the length/pointers of new elements */
@@ -1520,8 +1524,13 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_track_resize_indices(FLAC__St
free(track->indices);
track->indices = 0;
}
- else if ((track->indices = safe_realloc_(track->indices, new_size)) == NULL)
- return false;
+ else {
+ /* Leave track->indices untouched if realloc fails */
+ FLAC__StreamMetadata_CueSheet_Index *tmpptr;
+ if ((tmpptr = realloc(track->indices, new_size)) == NULL)
+ return false;
+ track->indices = tmpptr;
+ }
/* if growing, zero all the lengths/pointers of new elements */
if (new_size > old_size)
@@ -1615,8 +1624,13 @@ FLAC_API FLAC__bool FLAC__metadata_object_cuesheet_resize_tracks(FLAC__StreamMet
free(object->data.cue_sheet.tracks);
object->data.cue_sheet.tracks = 0;
}
- else if ((object->data.cue_sheet.tracks = safe_realloc_(object->data.cue_sheet.tracks, new_size)) == NULL)
- return false;
+ else {
+ /* Leave object->data.cue_sheet.tracks untouched if realloc fails */
+ FLAC__StreamMetadata_CueSheet_Track *tmpptr;
+ if ((tmpptr = realloc(object->data.cue_sheet.tracks, new_size)) == NULL)
+ return false;
+ object->data.cue_sheet.tracks = tmpptr;
+ }
/* if growing, zero all the lengths/pointers of new elements */
if (new_size > old_size)
--
2.27.0

View File

@ -2,7 +2,7 @@
Name: flac
Version: 1.3.4
Release: 1
Release: 2
Summary: encoder/decoder which support the Free Lossless Audio Codec
License: BSD and GPLv2+ and GFDL
Source0: http://downloads.xiph.org/releases/flac/flac-%{version}.tar.xz
@ -11,6 +11,9 @@ URL: http://www.xiph.org/flac/
%ifarch sw_64
Patch0000: flac-1.3.4-sw.patch
%endif
Patch0001: CVE-2020-22219-0001-fix-potential-memleak.patch
Patch0002: CVE-2020-22219-0002-Add-and-use-_nofree-variants-of-safe_realloc-functio.patch
Patch0003: CVE-2020-22219-0003-Leave-metadata-items-untouched-if-resize-function-fa.patch
Provides: %{name}-libs
Obsoletes: %{name}-libs
@ -102,6 +105,9 @@ update-desktop-database &> /dev/null || :
%doc flac-doc-devel/*
%changelog
* Tue Aug 29 2023 chenhaixiang<chenhaixiang3@huawei.com> - 1.3.4-2
- fix CVE-2020-22219
* Wed Nov 9 2022 chenhaixiang<chenhaixiang3@huawei.com> - 1.3.4-1
- update to 1.3.4