diff --git a/SOURCES/libsndfile-1.0.28-cve-2024-50612prereq.patch b/SOURCES/libsndfile-1.0.28-cve-2024-50612prereq.patch
new file mode 100644
index 0000000..60a9085
--- /dev/null
+++ b/SOURCES/libsndfile-1.0.28-cve-2024-50612prereq.patch
@@ -0,0 +1,67 @@
+diff -up libsndfile-1.0.28/src/ogg.c.cve-2024-50612prereq libsndfile-1.0.28/src/ogg.c
+--- libsndfile-1.0.28/src/ogg.c.cve-2024-50612prereq	2017-04-01 09:18:02.000000000 +0200
++++ libsndfile-1.0.28/src/ogg.c	2024-11-26 15:06:33.595446443 +0100
+@@ -45,6 +45,16 @@ static int	ogg_stream_classify (SF_PRIVA
+ static int	ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) ;
+ 
+ int
++ogg_write_page (SF_PRIVATE *psf, ogg_page *page)
++{	int bytes ;
++
++	bytes = psf_fwrite (page->header, 1, page->header_len, psf) ;
++	bytes += psf_fwrite (page->body, 1, page->body_len, psf) ;
++
++	return bytes == page->header_len + page->body_len ;
++} /* ogg_write_page */
++
++int
+ ogg_open (SF_PRIVATE *psf)
+ {	OGG_PRIVATE* odata = calloc (1, sizeof (OGG_PRIVATE)) ;
+ 	sf_count_t pos = psf_ftell (psf) ;
+diff -up libsndfile-1.0.28/src/ogg.h.cve-2024-50612prereq libsndfile-1.0.28/src/ogg.h
+--- libsndfile-1.0.28/src/ogg.h.cve-2024-50612prereq	2024-11-26 15:06:45.023560621 +0100
++++ libsndfile-1.0.28/src/ogg.h	2024-11-26 15:06:57.731687587 +0100
+@@ -48,5 +48,10 @@ typedef struct
+ 								(buf [base] & 0xff))
+ 
+ 
++/*
++** Write the whole Ogg page out. Convenience function as the ogg_page struct
++** splits header and body data into separate buffers.
++*/
++int	ogg_write_page	(SF_PRIVATE *, ogg_page *) ;
+ 
+ #endif /* SF_SRC_OGG_H */
+diff -up libsndfile-1.0.28/src/ogg_vorbis.c.cve-2024-50612prereq libsndfile-1.0.28/src/ogg_vorbis.c
+--- libsndfile-1.0.28/src/ogg_vorbis.c.cve-2024-50612prereq	2017-04-01 09:18:02.000000000 +0200
++++ libsndfile-1.0.28/src/ogg_vorbis.c	2024-11-26 15:06:33.595446443 +0100
+@@ -423,8 +423,7 @@ vorbis_write_header (SF_PRIVATE *psf, in
+ 		 * audio data will start on a new page, as per spec
+ 		 */
+ 		while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0)
+-		{	psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
+-			psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
++		{	ogg_write_page (psf, &odata->opage) ;
+ 			} ;
+ 	}
+ 
+@@ -463,8 +462,7 @@ vorbis_close (SF_PRIVATE *psf)
+ 				while (!odata->eos)
+ 				{	int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
+ 					if (result == 0) break ;
+-					psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
+-					psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
++					ogg_write_page (psf, &odata->opage) ;
+ 
+ 		/* this could be set above, but for illustrative purposes, I do
+ 		   it here (to show that vorbis does know where the stream ends) */
+@@ -778,8 +776,7 @@ vorbis_write_samples (SF_PRIVATE *psf, O
+ 			{	int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
+ 				if (result == 0)
+ 					break ;
+-				psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
+-				psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
++				ogg_write_page (psf, &odata->opage) ;
+ 
+ 				/*	This could be set above, but for illustrative purposes, I do
+ 				**	it here (to show that vorbis does know where the stream ends) */
diff --git a/SOURCES/libsndfile-1.2.2-cve-2024-50612.patch b/SOURCES/libsndfile-1.2.2-cve-2024-50612.patch
new file mode 100644
index 0000000..bfec2b6
--- /dev/null
+++ b/SOURCES/libsndfile-1.2.2-cve-2024-50612.patch
@@ -0,0 +1,324 @@
+diff -up libsndfile-1.0.28/src/ogg.c.cve-2024-50612 libsndfile-1.0.28/src/ogg.c
+--- libsndfile-1.0.28/src/ogg.c.cve-2024-50612	2024-11-25 23:52:41.158759323 +0100
++++ libsndfile-1.0.28/src/ogg.c	2024-11-25 23:53:45.520411291 +0100
+@@ -46,12 +46,16 @@ static int	ogg_page_classify (SF_PRIVATE
+ 
+ int
+ ogg_write_page (SF_PRIVATE *psf, ogg_page *page)
+-{	int bytes ;
++{	int n ;
+ 
+-	bytes = psf_fwrite (page->header, 1, page->header_len, psf) ;
+-	bytes += psf_fwrite (page->body, 1, page->body_len, psf) ;
++	n = psf_fwrite (page->header, 1, page->header_len, psf) ;
++	if (n == page->header_len)
++		n += psf_fwrite (page->body, 1, page->body_len, psf) ;
+ 
+-	return bytes == page->header_len + page->body_len ;
++	if (n != page->body_len + page->header_len)
++		return -1 ;
++
++	return n ;
+ } /* ogg_write_page */
+ 
+ int
+diff -up libsndfile-1.0.28/src/ogg_vorbis.c.cve-2024-50612 libsndfile-1.0.28/src/ogg_vorbis.c
+--- libsndfile-1.0.28/src/ogg_vorbis.c.cve-2024-50612	2024-11-25 23:52:41.156759303 +0100
++++ libsndfile-1.0.28/src/ogg_vorbis.c	2024-11-26 00:01:45.724339005 +0100
+@@ -76,25 +76,6 @@
+ 
+ #include "ogg.h"
+ 
+-typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ;
+-
+-static int	vorbis_read_header (SF_PRIVATE *psf, int log_data) ;
+-static int	vorbis_write_header (SF_PRIVATE *psf, int calc_length) ;
+-static int	vorbis_close (SF_PRIVATE *psf) ;
+-static int	vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
+-static int	vorbis_byterate (SF_PRIVATE *psf) ;
+-static sf_count_t	vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
+-static sf_count_t	vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
+-static sf_count_t	vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn) ;
+-static sf_count_t	vorbis_length (SF_PRIVATE *psf) ;
+-
+ typedef struct
+ {	int id ;
+ 	const char *name ;
+@@ -129,6 +110,42 @@ typedef struct
+ 	double quality ;
+ } VORBIS_PRIVATE ;
+ 
++typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ;
++
++static int	vorbis_read_header (SF_PRIVATE *psf, int log_data) ;
++static int	vorbis_write_header (SF_PRIVATE *psf, int calc_length) ;
++static int	vorbis_close (SF_PRIVATE *psf) ;
++static int	vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
++static int	vorbis_byterate (SF_PRIVATE *psf) ;
++static sf_count_t	vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
++static sf_count_t	vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
++static sf_count_t	vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn) ;
++static sf_count_t	vorbis_length (SF_PRIVATE *psf) ;
++static int	vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata, int in_frames) ;
++static void	vorbis_log_error (SF_PRIVATE *psf, int error) ;
++
++
++static void
++vorbis_log_error(SF_PRIVATE *psf, int error) {
++	switch (error)
++	{	case 0: return;
++		case OV_EIMPL:		psf->error = SFE_UNIMPLEMENTED ; break ;
++		case OV_ENOTVORBIS:	psf->error = SFE_MALFORMED_FILE ; break ;
++		case OV_EBADHEADER:	psf->error = SFE_MALFORMED_FILE ; break ;
++		case OV_EVERSION:	psf->error = SFE_UNSUPPORTED_ENCODING ; break ;
++		case OV_EFAULT:
++		case OV_EINVAL:
++		default: psf->error = SFE_INTERNAL ;
++		} ;
++} ;
++
+ static int
+ vorbis_read_header (SF_PRIVATE *psf, int log_data)
+ {
+@@ -412,7 +429,6 @@ vorbis_write_header (SF_PRIVATE *psf, in
+ 	{	ogg_packet header ;
+ 		ogg_packet header_comm ;
+ 		ogg_packet header_code ;
+-		int result ;
+ 
+ 		vorbis_analysis_headerout (&vdata->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ;
+ 		ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */
+@@ -422,9 +438,9 @@ vorbis_write_header (SF_PRIVATE *psf, in
+ 		/* This ensures the actual
+ 		 * audio data will start on a new page, as per spec
+ 		 */
+-		while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0)
+-		{	ogg_write_page (psf, &odata->opage) ;
+-			} ;
++		while (ogg_stream_flush (&odata->ostream, &odata->opage))
++			if (ogg_write_page (psf, &odata->opage) < 0)
++				return -1 ;
+ 	}
+ 
+ 	return 0 ;
+@@ -434,6 +450,7 @@ static int
+ vorbis_close (SF_PRIVATE *psf)
+ {	OGG_PRIVATE* odata = psf->container_data ;
+ 	VORBIS_PRIVATE *vdata = psf->codec_data ;
++	int ret = 0 ;
+ 
+ 	if (odata == NULL || vdata == NULL)
+ 		return 0 ;
+@@ -444,34 +461,14 @@ vorbis_close (SF_PRIVATE *psf)
+ 	if (psf->file.mode == SFM_WRITE)
+ 	{
+ 		if (psf->write_current <= 0)
+-			vorbis_write_header (psf, 0) ;
+-
+-		vorbis_analysis_wrote (&vdata->vdsp, 0) ;
+-		while (vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock) == 1)
+-		{
++			ret = vorbis_write_header (psf, 0) ;
+ 
+-		/* analysis, assume we want to use bitrate management */
+-			vorbis_analysis (&vdata->vblock, NULL) ;
+-			vorbis_bitrate_addblock (&vdata->vblock) ;
+-
+-			while (vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket))
+-			{	/* weld the packet into the bitstream */
+-				ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
+-
+-				/* write out pages (if any) */
+-				while (!odata->eos)
+-				{	int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
+-					if (result == 0) break ;
+-					ogg_write_page (psf, &odata->opage) ;
+-
+-		/* this could be set above, but for illustrative purposes, I do
+-		   it here (to show that vorbis does know where the stream ends) */
+-
+-					if (ogg_page_eos (&odata->opage)) odata->eos = 1 ;
+-				}
+-			}
+-		}
+-	}
++		if (ret == 0)
++		{	/* A write of zero samples tells Vorbis the stream is done and to
++			   flush. */
++			ret = vorbis_write_samples (psf, odata, vdata, 0) ;
++			} ;
++		} ;
+ 
+ 	/* ogg_page and ogg_packet structs always point to storage in
+ 	   libvorbis.  They are never freed or manipulated directly */
+@@ -481,7 +478,7 @@ vorbis_close (SF_PRIVATE *psf)
+ 	vorbis_comment_clear (&vdata->vcomment) ;
+ 	vorbis_info_clear (&vdata->vinfo) ;
+ 
+-	return 0 ;
++	return ret ;
+ } /* vorbis_close */
+ 
+ int
+@@ -750,33 +747,40 @@ vorbis_read_d (SF_PRIVATE *psf, double *
+ /*==============================================================================
+ */
+ 
+-static void
++static int
+ vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata, int in_frames)
+-{
+-	vorbis_analysis_wrote (&vdata->vdsp, in_frames) ;
++{	int ret ;
++
++	if ((ret = vorbis_analysis_wrote (&vdata->vdsp, in_frames)) != 0)
++		return ret ;
+ 
+ 	/*
+ 	**	Vorbis does some data preanalysis, then divvies up blocks for
+ 	**	more involved (potentially parallel) processing. Get a single
+ 	**	block for encoding now.
+ 	*/
+-	while (vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock) == 1)
++	while ((ret = vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock)) == 1)
+ 	{
+ 		/* analysis, assume we want to use bitrate management */
+-		vorbis_analysis (&vdata->vblock, NULL) ;
+-		vorbis_bitrate_addblock (&vdata->vblock) ;
++		if ((ret = vorbis_analysis (&vdata->vblock, NULL)) != 0)
++			return ret ;
++		if ((ret = vorbis_bitrate_addblock (&vdata->vblock)) != 0)
++			return ret ;
+ 
+-		while (vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket))
++		while ((ret = vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket)) == 1)
+ 		{
+ 			/* weld the packet into the bitstream */
+-			ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
++			if ((ret = ogg_stream_packetin (&odata->ostream, &odata->opacket)) != 0)
++				return ret ;
+ 
+ 			/* write out pages (if any) */
+ 			while (!odata->eos)
+-			{	int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
+-				if (result == 0)
++			{	ret = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
++				if (ret == 0)
+ 					break ;
+-				ogg_write_page (psf, &odata->opage) ;
++
++				if (ogg_write_page (psf, &odata->opage) < 0)
++					return -1 ;
+ 
+ 				/*	This could be set above, but for illustrative purposes, I do
+ 				**	it here (to show that vorbis does know where the stream ends) */
+@@ -784,16 +788,22 @@ vorbis_write_samples (SF_PRIVATE *psf, O
+ 					odata->eos = 1 ;
+ 				} ;
+ 			} ;
++		if (ret != 0)
++			return ret ;
+ 		} ;
++	if (ret != 0)
++		return ret ;
+ 
+ 	vdata->loc += in_frames ;
++
++	return 0 ;
+ } /* vorbis_write_data */
+ 
+ 
+ static sf_count_t
+ vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t lens)
+ {
+-	int i, m, j = 0 ;
++	int i, m, j = 0, ret ;
+ 	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+ 	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
+ 	int in_frames = lens / psf->sf.channels ;
+@@ -802,14 +812,17 @@ vorbis_write_s (SF_PRIVATE *psf, const s
+ 		for (m = 0 ; m < psf->sf.channels ; m++)
+ 			buffer [m][i] = (float) (ptr [j++]) / 32767.0f ;
+ 
+-	vorbis_write_samples (psf, odata, vdata, in_frames) ;
++	if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)))
++	{	vorbis_log_error (psf, ret) ;
++		return 0 ;
++		} ;
+ 
+ 	return lens ;
+ } /* vorbis_write_s */
+ 
+ static sf_count_t
+ vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t lens)
+-{	int i, m, j = 0 ;
++{	int i, m, j = 0, ret ;
+ 	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+ 	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
+ 	int in_frames = lens / psf->sf.channels ;
+@@ -818,14 +831,17 @@ vorbis_write_i (SF_PRIVATE *psf, const i
+ 		for (m = 0 ; m < psf->sf.channels ; m++)
+ 			buffer [m][i] = (float) (ptr [j++]) / 2147483647.0f ;
+ 
+-	vorbis_write_samples (psf, odata, vdata, in_frames) ;
++	if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)))
++	{	vorbis_log_error (psf, ret) ;
++		return 0 ;
++		} ;
+ 
+ 	return lens ;
+ } /* vorbis_write_i */
+ 
+ static sf_count_t
+ vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t lens)
+-{	int i, m, j = 0 ;
++{	int i, m, j = 0, ret ;
+ 	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+ 	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
+ 	int in_frames = lens / psf->sf.channels ;
+@@ -834,14 +850,17 @@ vorbis_write_f (SF_PRIVATE *psf, const f
+ 		for (m = 0 ; m < psf->sf.channels ; m++)
+ 			buffer [m][i] = ptr [j++] ;
+ 
+-	vorbis_write_samples (psf, odata, vdata, in_frames) ;
++	if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)) != 0)
++	{	vorbis_log_error (psf, ret) ;
++		return 0 ;
++		} ;
+ 
+ 	return lens ;
+ } /* vorbis_write_f */
+ 
+ static sf_count_t
+ vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens)
+-{	int i, m, j = 0 ;
++{	int i, m, j = 0, ret ;
+ 	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
+ 	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
+ 	int in_frames = lens / psf->sf.channels ;
+@@ -850,7 +869,10 @@ vorbis_write_d (SF_PRIVATE *psf, const d
+ 		for (m = 0 ; m < psf->sf.channels ; m++)
+ 			buffer [m][i] = (float) ptr [j++] ;
+ 
+-	vorbis_write_samples (psf, odata, vdata, in_frames) ;
++	if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)) != 0)
++	{	vorbis_log_error (psf, ret) ;
++		return 0 ;
++		} ;
+ 
+ 	return lens ;
+ } /* vorbis_write_d */
diff --git a/SPECS/libsndfile.spec b/SPECS/libsndfile.spec
index 1f55802..ec15180 100644
--- a/SPECS/libsndfile.spec
+++ b/SPECS/libsndfile.spec
@@ -1,7 +1,7 @@
 Summary:	Library for reading and writing sound files
 Name:		libsndfile
 Version:	1.0.28
-Release:	14%{?dist}
+Release:	16%{?dist}
 License:	LGPLv2+ and GPLv2+ and BSD
 Group:		System Environment/Libraries
 URL:		http://www.mega-nerd.com/libsndfile/
@@ -23,6 +23,9 @@ Patch10:	libsndfile-1.0.31-deb669ee.patch
 Patch11:	libsndfile-1.0.31-ced91d7b.patch
 # from upstream, fix #RHEL-3750, for <= 1.2.2
 Patch12:	libsndfile-1.0.31-pullrequest979.patch
+# from upstream, for <= 1.2.2, #RHEL-65095
+Patch13:	libsndfile-1.0.28-cve-2024-50612prereq.patch
+Patch14:	libsndfile-1.2.2-cve-2024-50612.patch
 BuildRequires:	alsa-lib-devel
 BuildRequires:	flac-devel
 BuildRequires:	libogg-devel
@@ -80,6 +83,8 @@ This package contains command line utilities for libsndfile.
 %patch -P 10 -p1 -b .deb669ee
 %patch -P 11 -p1 -b .ced91d7b
 %patch -P 12 -p1 -b .pullrequest979
+%patch -P 13 -p1 -b .cve-2024-50612prereq
+%patch -P 14 -p1 -b .cve-2024-50612
 rm -r src/GSM610
 
 %build
@@ -175,6 +180,12 @@ LD_LIBRARY_PATH=$PWD/src/.libs make check
 
 
 %changelog
+* Tue Nov 26 2024 Michal Hlavinka <mhlavink@redhat.com> - 1.0.28-16
+- fix prerequisit patch (#RHEL-65093)
+
+* Wed Nov 20 2024 Michal Hlavinka <mhlavink@redhat.com> - 1.0.28-15
+- fix crash in ogg vorbis (#RHEL-65093) (CVE-2024-50612)
+
 * Wed Nov 01 2023 Michal Hlavinka <mhlavink@redhat.com> - 1.0.28-14
 - fix integer overflows causing CVE-2022-33065 (#RHEL-3750)