123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- From 4755f5bd7854611d92ad0f1295587b439f9950ba 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
- Upstream: https://github.com/libsndfile/libsndfile/commit/4755f5bd7854611d92ad0f1295587b439f9950ba
- Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
- ---
- 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 529941af..e2d679d4 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 511653ec..e01224b9 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 add12396..fae252ca 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) ;
- + ret = vorbis_write_header (psf, 0) ;
-
- - vorbis_analysis_wrote (&vdata->vdsp, 0) ;
- - while (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) ;
- -
- - 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
- --
- 2.39.5
|