Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:h31
libsndfile
libsndfile-CVE-2024-50612.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File libsndfile-CVE-2024-50612.patch of Package libsndfile
From 274198fd95152b412ada49be059258ec0efca272 Mon Sep 17 00:00:00 2001 From: Arthur Taylor <art@ified.ca> Date: Fri, 15 Nov 2024 19:46:53 -0800 Subject: [PATCH] src/ogg: better error checking for vorbis. Fixes #1035 --- src/ogg.c | 12 ++-- src/ogg_opus.c | 17 +++-- src/ogg_vorbis.c | 170 ++++++++++++++++++++++++++--------------------- 3 files changed, 114 insertions(+), 85 deletions(-) diff --git a/src/ogg.c b/src/ogg.c index 529941af8..e2d679d41 100644 --- a/src/ogg.c +++ b/src/ogg.c @@ -211,12 +211,16 @@ ogg_read_first_page (SF_PRIVATE *psf, OGG_PRIVATE *odata) 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 */ sf_count_t diff --git a/src/ogg_opus.c b/src/ogg_opus.c index 511653ecc..e01224b99 100644 --- a/src/ogg_opus.c +++ b/src/ogg_opus.c @@ -827,15 +827,16 @@ ogg_opus_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) /* The first page MUST only contain the header, so flush it out now */ ogg_stream_packetin (&odata->ostream, &op) ; - for ( ; (nn = ogg_stream_flush (&odata->ostream, &odata->opage)) ; ) - { if (! (nn = ogg_write_page (psf, &odata->opage))) + while (ogg_stream_flush (&odata->ostream, &odata->opage)) + { nn = ogg_write_page (psf, &odata->opage) ; + if (nn < 0) { psf_log_printf (psf, "Opus : Failed to write header!\n") ; if (psf->error) return psf->error ; return SFE_INTERNAL ; } ; psf->dataoffset += nn ; - } + } ; /* ** Metadata Tags (manditory) @@ -850,15 +851,16 @@ ogg_opus_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) vorbiscomment_write_tags (psf, &op, &opustags_ident, opus_get_version_string (), - (OGG_OPUS_COMMENT_PAD)) ; op.packetno = 2 ; ogg_stream_packetin (&odata->ostream, &op) ; - for ( ; (nn = ogg_stream_flush (&odata->ostream, &odata->opage)) ; ) - { if (! (nn = ogg_write_page (psf, &odata->opage))) + while (ogg_stream_flush (&odata->ostream, &odata->opage)) + { nn = ogg_write_page (psf, &odata->opage) ; + if (nn < 0) { psf_log_printf (psf, "Opus : Failed to write comments!\n") ; if (psf->error) return psf->error ; return SFE_INTERNAL ; } ; psf->dataoffset += nn ; - } + } ; return 0 ; } /* ogg_opus_write_header */ @@ -1132,7 +1134,8 @@ ogg_opus_write_out (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus) if (nbytes > 0) { oopus->u.encode.last_segments -= ogg_page_segments (&odata->opage) ; oopus->pg_pos = oopus->pkt_pos ; - ogg_write_page (psf, &odata->opage) ; + if (ogg_write_page (psf, &odata->opage) < 0) + return -1 ; } else break ; diff --git a/src/ogg_vorbis.c b/src/ogg_vorbis.c index add123966..fae252ca0 100644 --- a/src/ogg_vorbis.c +++ b/src/ogg_vorbis.c @@ -82,28 +82,6 @@ /* How many seconds in the future to not bother bisection searching for. */ #define VORBIS_SEEK_THRESHOLD 2 -typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ; - -static int vorbis_read_header (SF_PRIVATE *psf) ; -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 int vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) ; -static int vorbis_skip (SF_PRIVATE *psf, uint64_t target_gp) ; -static int vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) ; -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 int vorbis_rnull (SF_PRIVATE *psf, int samples, void *vptr, int off , int channels, float **pcm) ; - typedef struct { int id ; const char *name ; @@ -145,6 +123,45 @@ typedef struct sf_count_t last_page ; } VORBIS_PRIVATE ; +typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ; + +static int vorbis_read_header (SF_PRIVATE *psf) ; +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 int vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) ; +static int vorbis_skip (SF_PRIVATE *psf, uint64_t target_gp) ; +static int vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) ; +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 int vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata, int in_frames) ; +static int vorbis_rnull (SF_PRIVATE *psf, int samples, void *vptr, int off , int channels, float **pcm) ; +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) { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ; @@ -380,7 +397,6 @@ vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) { 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 */ @@ -390,9 +406,9 @@ vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length)) /* 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 ; @@ -402,6 +418,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 ; @@ -412,34 +429,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 */ @@ -449,7 +446,7 @@ vorbis_close (SF_PRIVATE *psf) vorbis_comment_clear (&vdata->vcomment) ; vorbis_info_clear (&vdata->vinfo) ; - return 0 ; + return ret ; } /* vorbis_close */ int @@ -688,33 +685,40 @@ vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t lens) /*============================================================================== */ -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) */ @@ -722,16 +726,22 @@ vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata odata->eos = 1 ; } ; } ; + if (ret != 0) + return ret ; } ; + if (ret != 0) + return ret ; vdata->gp += 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 ; @@ -740,14 +750,17 @@ vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t lens) 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 ; @@ -756,14 +769,17 @@ vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t lens) 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 ; @@ -772,14 +788,17 @@ vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t lens) 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 ; @@ -788,7 +807,10 @@ vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens) 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 */ @@ -884,7 +906,7 @@ vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) return 0 ; /* Search for a position a half large-block before our target. As Vorbis is - ** lapped, every sample position come from two blocks, the "left" half of + ** lapped, every sample position comes from two blocks, the "left" half of ** one block and the "right" half of the previous block. The granule ** position of an Ogg page of a Vorbis stream is the sample offset of the ** last finished sample in the stream that can be decoded from a page. A
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor