0014-src-ogg-better-error-checking-for-vorbis.-Fixes-1035.patch 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. From 4755f5bd7854611d92ad0f1295587b439f9950ba Mon Sep 17 00:00:00 2001
  2. From: Arthur Taylor <art@ified.ca>
  3. Date: Fri, 15 Nov 2024 19:46:53 -0800
  4. Subject: [PATCH] src/ogg: better error checking for vorbis. Fixes #1035
  5. Upstream: https://github.com/libsndfile/libsndfile/commit/4755f5bd7854611d92ad0f1295587b439f9950ba
  6. Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
  7. ---
  8. src/ogg.c | 12 ++--
  9. src/ogg_opus.c | 17 +++--
  10. src/ogg_vorbis.c | 170 ++++++++++++++++++++++++++---------------------
  11. 3 files changed, 114 insertions(+), 85 deletions(-)
  12. diff --git a/src/ogg.c b/src/ogg.c
  13. index 529941af..e2d679d4 100644
  14. --- a/src/ogg.c
  15. +++ b/src/ogg.c
  16. @@ -211,12 +211,16 @@ ogg_read_first_page (SF_PRIVATE *psf, OGG_PRIVATE *odata)
  17. int
  18. ogg_write_page (SF_PRIVATE *psf, ogg_page *page)
  19. -{ int bytes ;
  20. +{ int n ;
  21. - bytes = psf_fwrite (page->header, 1, page->header_len, psf) ;
  22. - bytes += psf_fwrite (page->body, 1, page->body_len, psf) ;
  23. + n = psf_fwrite (page->header, 1, page->header_len, psf) ;
  24. + if (n == page->header_len)
  25. + n += psf_fwrite (page->body, 1, page->body_len, psf) ;
  26. - return bytes == page->header_len + page->body_len ;
  27. + if (n != page->body_len + page->header_len)
  28. + return -1 ;
  29. +
  30. + return n ;
  31. } /* ogg_write_page */
  32. sf_count_t
  33. diff --git a/src/ogg_opus.c b/src/ogg_opus.c
  34. index 511653ec..e01224b9 100644
  35. --- a/src/ogg_opus.c
  36. +++ b/src/ogg_opus.c
  37. @@ -827,15 +827,16 @@ ogg_opus_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
  38. /* The first page MUST only contain the header, so flush it out now */
  39. ogg_stream_packetin (&odata->ostream, &op) ;
  40. - for ( ; (nn = ogg_stream_flush (&odata->ostream, &odata->opage)) ; )
  41. - { if (! (nn = ogg_write_page (psf, &odata->opage)))
  42. + while (ogg_stream_flush (&odata->ostream, &odata->opage))
  43. + { nn = ogg_write_page (psf, &odata->opage) ;
  44. + if (nn < 0)
  45. { psf_log_printf (psf, "Opus : Failed to write header!\n") ;
  46. if (psf->error)
  47. return psf->error ;
  48. return SFE_INTERNAL ;
  49. } ;
  50. psf->dataoffset += nn ;
  51. - }
  52. + } ;
  53. /*
  54. ** Metadata Tags (manditory)
  55. @@ -850,15 +851,16 @@ ogg_opus_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
  56. vorbiscomment_write_tags (psf, &op, &opustags_ident, opus_get_version_string (), - (OGG_OPUS_COMMENT_PAD)) ;
  57. op.packetno = 2 ;
  58. ogg_stream_packetin (&odata->ostream, &op) ;
  59. - for ( ; (nn = ogg_stream_flush (&odata->ostream, &odata->opage)) ; )
  60. - { if (! (nn = ogg_write_page (psf, &odata->opage)))
  61. + while (ogg_stream_flush (&odata->ostream, &odata->opage))
  62. + { nn = ogg_write_page (psf, &odata->opage) ;
  63. + if (nn < 0)
  64. { psf_log_printf (psf, "Opus : Failed to write comments!\n") ;
  65. if (psf->error)
  66. return psf->error ;
  67. return SFE_INTERNAL ;
  68. } ;
  69. psf->dataoffset += nn ;
  70. - }
  71. + } ;
  72. return 0 ;
  73. } /* ogg_opus_write_header */
  74. @@ -1132,7 +1134,8 @@ ogg_opus_write_out (SF_PRIVATE *psf, OGG_PRIVATE *odata, OPUS_PRIVATE *oopus)
  75. if (nbytes > 0)
  76. { oopus->u.encode.last_segments -= ogg_page_segments (&odata->opage) ;
  77. oopus->pg_pos = oopus->pkt_pos ;
  78. - ogg_write_page (psf, &odata->opage) ;
  79. + if (ogg_write_page (psf, &odata->opage) < 0)
  80. + return -1 ;
  81. }
  82. else
  83. break ;
  84. diff --git a/src/ogg_vorbis.c b/src/ogg_vorbis.c
  85. index add12396..fae252ca 100644
  86. --- a/src/ogg_vorbis.c
  87. +++ b/src/ogg_vorbis.c
  88. @@ -82,28 +82,6 @@
  89. /* How many seconds in the future to not bother bisection searching for. */
  90. #define VORBIS_SEEK_THRESHOLD 2
  91. -typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ;
  92. -
  93. -static int vorbis_read_header (SF_PRIVATE *psf) ;
  94. -static int vorbis_write_header (SF_PRIVATE *psf, int calc_length) ;
  95. -static int vorbis_close (SF_PRIVATE *psf) ;
  96. -static int vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
  97. -static int vorbis_byterate (SF_PRIVATE *psf) ;
  98. -static int vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) ;
  99. -static int vorbis_skip (SF_PRIVATE *psf, uint64_t target_gp) ;
  100. -static int vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) ;
  101. -static sf_count_t vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
  102. -static sf_count_t vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
  103. -static sf_count_t vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
  104. -static sf_count_t vorbis_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
  105. -static sf_count_t vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
  106. -static sf_count_t vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
  107. -static sf_count_t vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
  108. -static sf_count_t vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
  109. -static sf_count_t vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
  110. -static sf_count_t vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn) ;
  111. -static int vorbis_rnull (SF_PRIVATE *psf, int samples, void *vptr, int off , int channels, float **pcm) ;
  112. -
  113. typedef struct
  114. { int id ;
  115. const char *name ;
  116. @@ -145,6 +123,45 @@ typedef struct
  117. sf_count_t last_page ;
  118. } VORBIS_PRIVATE ;
  119. +typedef int convert_func (SF_PRIVATE *psf, int, void *, int, int, float **) ;
  120. +
  121. +static int vorbis_read_header (SF_PRIVATE *psf) ;
  122. +static int vorbis_write_header (SF_PRIVATE *psf, int calc_length) ;
  123. +static int vorbis_close (SF_PRIVATE *psf) ;
  124. +static int vorbis_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
  125. +static int vorbis_byterate (SF_PRIVATE *psf) ;
  126. +static int vorbis_calculate_granulepos (SF_PRIVATE *psf, uint64_t *gp_out) ;
  127. +static int vorbis_skip (SF_PRIVATE *psf, uint64_t target_gp) ;
  128. +static int vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp) ;
  129. +static sf_count_t vorbis_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
  130. +static sf_count_t vorbis_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
  131. +static sf_count_t vorbis_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
  132. +static sf_count_t vorbis_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
  133. +static sf_count_t vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
  134. +static sf_count_t vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
  135. +static sf_count_t vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
  136. +static sf_count_t vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
  137. +static sf_count_t vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
  138. +static sf_count_t vorbis_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn) ;
  139. +static int vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata, int in_frames) ;
  140. +static int vorbis_rnull (SF_PRIVATE *psf, int samples, void *vptr, int off , int channels, float **pcm) ;
  141. +static void vorbis_log_error (SF_PRIVATE *psf, int error) ;
  142. +
  143. +
  144. +static void
  145. +vorbis_log_error(SF_PRIVATE *psf, int error) {
  146. + switch (error)
  147. + { case 0: return;
  148. + case OV_EIMPL: psf->error = SFE_UNIMPLEMENTED ; break ;
  149. + case OV_ENOTVORBIS: psf->error = SFE_MALFORMED_FILE ; break ;
  150. + case OV_EBADHEADER: psf->error = SFE_MALFORMED_FILE ; break ;
  151. + case OV_EVERSION: psf->error = SFE_UNSUPPORTED_ENCODING ; break ;
  152. + case OV_EFAULT:
  153. + case OV_EINVAL:
  154. + default: psf->error = SFE_INTERNAL ;
  155. + } ;
  156. +} ;
  157. +
  158. static int
  159. vorbis_read_header (SF_PRIVATE *psf)
  160. { OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
  161. @@ -380,7 +397,6 @@ vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
  162. { ogg_packet header ;
  163. ogg_packet header_comm ;
  164. ogg_packet header_code ;
  165. - int result ;
  166. vorbis_analysis_headerout (&vdata->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ;
  167. ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */
  168. @@ -390,9 +406,9 @@ vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
  169. /* This ensures the actual
  170. * audio data will start on a new page, as per spec
  171. */
  172. - while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0)
  173. - { ogg_write_page (psf, &odata->opage) ;
  174. - } ;
  175. + while (ogg_stream_flush (&odata->ostream, &odata->opage))
  176. + if (ogg_write_page (psf, &odata->opage) < 0)
  177. + return -1 ;
  178. }
  179. return 0 ;
  180. @@ -402,6 +418,7 @@ static int
  181. vorbis_close (SF_PRIVATE *psf)
  182. { OGG_PRIVATE* odata = psf->container_data ;
  183. VORBIS_PRIVATE *vdata = psf->codec_data ;
  184. + int ret = 0 ;
  185. if (odata == NULL || vdata == NULL)
  186. return 0 ;
  187. @@ -412,34 +429,14 @@ vorbis_close (SF_PRIVATE *psf)
  188. if (psf->file.mode == SFM_WRITE)
  189. {
  190. if (psf->write_current <= 0)
  191. - vorbis_write_header (psf, 0) ;
  192. + ret = vorbis_write_header (psf, 0) ;
  193. - vorbis_analysis_wrote (&vdata->vdsp, 0) ;
  194. - while (vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock) == 1)
  195. - {
  196. -
  197. - /* analysis, assume we want to use bitrate management */
  198. - vorbis_analysis (&vdata->vblock, NULL) ;
  199. - vorbis_bitrate_addblock (&vdata->vblock) ;
  200. -
  201. - while (vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket))
  202. - { /* weld the packet into the bitstream */
  203. - ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
  204. -
  205. - /* write out pages (if any) */
  206. - while (!odata->eos)
  207. - { int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
  208. - if (result == 0) break ;
  209. - ogg_write_page (psf, &odata->opage) ;
  210. -
  211. - /* this could be set above, but for illustrative purposes, I do
  212. - it here (to show that vorbis does know where the stream ends) */
  213. -
  214. - if (ogg_page_eos (&odata->opage)) odata->eos = 1 ;
  215. - }
  216. - }
  217. - }
  218. - }
  219. + if (ret == 0)
  220. + { /* A write of zero samples tells Vorbis the stream is done and to
  221. + flush. */
  222. + ret = vorbis_write_samples (psf, odata, vdata, 0) ;
  223. + } ;
  224. + } ;
  225. /* ogg_page and ogg_packet structs always point to storage in
  226. libvorbis. They are never freed or manipulated directly */
  227. @@ -449,7 +446,7 @@ vorbis_close (SF_PRIVATE *psf)
  228. vorbis_comment_clear (&vdata->vcomment) ;
  229. vorbis_info_clear (&vdata->vinfo) ;
  230. - return 0 ;
  231. + return ret ;
  232. } /* vorbis_close */
  233. int
  234. @@ -688,33 +685,40 @@ vorbis_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t lens)
  235. /*==============================================================================
  236. */
  237. -static void
  238. +static int
  239. vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata, int in_frames)
  240. -{
  241. - vorbis_analysis_wrote (&vdata->vdsp, in_frames) ;
  242. +{ int ret ;
  243. +
  244. + if ((ret = vorbis_analysis_wrote (&vdata->vdsp, in_frames)) != 0)
  245. + return ret ;
  246. /*
  247. ** Vorbis does some data preanalysis, then divvies up blocks for
  248. ** more involved (potentially parallel) processing. Get a single
  249. ** block for encoding now.
  250. */
  251. - while (vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock) == 1)
  252. + while ((ret = vorbis_analysis_blockout (&vdata->vdsp, &vdata->vblock)) == 1)
  253. {
  254. /* analysis, assume we want to use bitrate management */
  255. - vorbis_analysis (&vdata->vblock, NULL) ;
  256. - vorbis_bitrate_addblock (&vdata->vblock) ;
  257. + if ((ret = vorbis_analysis (&vdata->vblock, NULL)) != 0)
  258. + return ret ;
  259. + if ((ret = vorbis_bitrate_addblock (&vdata->vblock)) != 0)
  260. + return ret ;
  261. - while (vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket))
  262. + while ((ret = vorbis_bitrate_flushpacket (&vdata->vdsp, &odata->opacket)) == 1)
  263. {
  264. /* weld the packet into the bitstream */
  265. - ogg_stream_packetin (&odata->ostream, &odata->opacket) ;
  266. + if ((ret = ogg_stream_packetin (&odata->ostream, &odata->opacket)) != 0)
  267. + return ret ;
  268. /* write out pages (if any) */
  269. while (!odata->eos)
  270. - { int result = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
  271. - if (result == 0)
  272. + { ret = ogg_stream_pageout (&odata->ostream, &odata->opage) ;
  273. + if (ret == 0)
  274. break ;
  275. - ogg_write_page (psf, &odata->opage) ;
  276. +
  277. + if (ogg_write_page (psf, &odata->opage) < 0)
  278. + return -1 ;
  279. /* This could be set above, but for illustrative purposes, I do
  280. ** it here (to show that vorbis does know where the stream ends) */
  281. @@ -722,16 +726,22 @@ vorbis_write_samples (SF_PRIVATE *psf, OGG_PRIVATE *odata, VORBIS_PRIVATE *vdata
  282. odata->eos = 1 ;
  283. } ;
  284. } ;
  285. + if (ret != 0)
  286. + return ret ;
  287. } ;
  288. + if (ret != 0)
  289. + return ret ;
  290. vdata->gp += in_frames ;
  291. +
  292. + return 0 ;
  293. } /* vorbis_write_data */
  294. static sf_count_t
  295. vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t lens)
  296. {
  297. - int i, m, j = 0 ;
  298. + int i, m, j = 0, ret ;
  299. OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
  300. VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
  301. int in_frames = lens / psf->sf.channels ;
  302. @@ -740,14 +750,17 @@ vorbis_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t lens)
  303. for (m = 0 ; m < psf->sf.channels ; m++)
  304. buffer [m][i] = (float) (ptr [j++]) / 32767.0f ;
  305. - vorbis_write_samples (psf, odata, vdata, in_frames) ;
  306. + if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)))
  307. + { vorbis_log_error (psf, ret) ;
  308. + return 0 ;
  309. + } ;
  310. return lens ;
  311. } /* vorbis_write_s */
  312. static sf_count_t
  313. vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t lens)
  314. -{ int i, m, j = 0 ;
  315. +{ int i, m, j = 0, ret ;
  316. OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
  317. VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
  318. int in_frames = lens / psf->sf.channels ;
  319. @@ -756,14 +769,17 @@ vorbis_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t lens)
  320. for (m = 0 ; m < psf->sf.channels ; m++)
  321. buffer [m][i] = (float) (ptr [j++]) / 2147483647.0f ;
  322. - vorbis_write_samples (psf, odata, vdata, in_frames) ;
  323. + if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)))
  324. + { vorbis_log_error (psf, ret) ;
  325. + return 0 ;
  326. + } ;
  327. return lens ;
  328. } /* vorbis_write_i */
  329. static sf_count_t
  330. vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t lens)
  331. -{ int i, m, j = 0 ;
  332. +{ int i, m, j = 0, ret ;
  333. OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
  334. VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
  335. int in_frames = lens / psf->sf.channels ;
  336. @@ -772,14 +788,17 @@ vorbis_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t lens)
  337. for (m = 0 ; m < psf->sf.channels ; m++)
  338. buffer [m][i] = ptr [j++] ;
  339. - vorbis_write_samples (psf, odata, vdata, in_frames) ;
  340. + if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)) != 0)
  341. + { vorbis_log_error (psf, ret) ;
  342. + return 0 ;
  343. + } ;
  344. return lens ;
  345. } /* vorbis_write_f */
  346. static sf_count_t
  347. vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens)
  348. -{ int i, m, j = 0 ;
  349. +{ int i, m, j = 0, ret ;
  350. OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
  351. VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
  352. int in_frames = lens / psf->sf.channels ;
  353. @@ -788,7 +807,10 @@ vorbis_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t lens)
  354. for (m = 0 ; m < psf->sf.channels ; m++)
  355. buffer [m][i] = (float) ptr [j++] ;
  356. - vorbis_write_samples (psf, odata, vdata, in_frames) ;
  357. + if ((ret = vorbis_write_samples (psf, odata, vdata, in_frames)) != 0)
  358. + { vorbis_log_error (psf, ret) ;
  359. + return 0 ;
  360. + } ;
  361. return lens ;
  362. } /* vorbis_write_d */
  363. @@ -884,7 +906,7 @@ vorbis_seek_trysearch (SF_PRIVATE *psf, uint64_t target_gp)
  364. return 0 ;
  365. /* Search for a position a half large-block before our target. As Vorbis is
  366. - ** lapped, every sample position come from two blocks, the "left" half of
  367. + ** lapped, every sample position comes from two blocks, the "left" half of
  368. ** one block and the "right" half of the previous block. The granule
  369. ** position of an Ogg page of a Vorbis stream is the sample offset of the
  370. ** last finished sample in the stream that can be decoded from a page. A
  371. --
  372. 2.39.5