avformat/sbgdec: Use avio_read_to_bprint() where appropriate

Note: There is a slight difference in the handling of
the max_file_size option: The earlier code used it to mean
to limit the size of the buffer to allocate; the new code
treats it more literally as maximum size to read from
the input.

Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt 2023-08-08 06:47:50 +02:00
parent 9583a2c8eb
commit 7a2b587dea

View File

@ -22,6 +22,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include "libavutil/bprint.h"
#include "libavutil/channel_layout.h" #include "libavutil/channel_layout.h"
#include "libavutil/intreadwrite.h" #include "libavutil/intreadwrite.h"
#include "libavutil/log.h" #include "libavutil/log.h"
@ -859,37 +860,20 @@ fail:
return r; return r;
} }
static int read_whole_file(AVIOContext *io, int max_size, char **rbuf) static int read_whole_file(AVIOContext *io, int max_size, AVBPrint *rbuf)
{ {
char *buf = NULL; int ret = avio_read_to_bprint(io, rbuf, max_size);
int size = 0, bufsize = 0, r; if (ret < 0)
return ret;
while (1) { if (!av_bprint_is_complete(rbuf))
if (bufsize - size < 1024) { return AVERROR(ENOMEM);
bufsize = FFMIN(FFMAX(2 * bufsize, 8192), max_size); /* Check if we have read the whole file. AVIOContext.eof_reached is only
if (bufsize - size < 2) { * set after a read failed due to EOF, so this check is incorrect in case
size = AVERROR(EFBIG); * max_size equals the actual file size, but checking for that would
goto fail; * require attempting to read beyond max_size. */
} if (!io->eof_reached)
buf = av_realloc_f(buf, bufsize, 1); return AVERROR(EFBIG);
if (!buf) { return 0;
size = AVERROR(ENOMEM);
goto fail;
}
}
r = avio_read(io, buf, bufsize - size - 1);
if (r == AVERROR_EOF)
break;
if (r < 0)
goto fail;
size += r;
}
buf[size] = 0;
*rbuf = buf;
return size;
fail:
av_free(buf);
return size;
} }
static int expand_timestamps(void *log, struct sbg_script *s) static int expand_timestamps(void *log, struct sbg_script *s)
@ -1407,19 +1391,21 @@ static av_cold int sbg_read_probe(const AVProbeData *p)
static av_cold int sbg_read_header(AVFormatContext *avf) static av_cold int sbg_read_header(AVFormatContext *avf)
{ {
struct sbg_demuxer *sbg = avf->priv_data; struct sbg_demuxer *sbg = avf->priv_data;
AVBPrint bprint;
int r; int r;
char *buf = NULL;
struct sbg_script script = { 0 }; struct sbg_script script = { 0 };
AVStream *st; AVStream *st;
FFStream *sti; FFStream *sti;
struct ws_intervals inter = { 0 }; struct ws_intervals inter = { 0 };
r = read_whole_file(avf->pb, sbg->max_file_size, &buf); av_bprint_init(&bprint, 0, sbg->max_file_size + 1U);
r = read_whole_file(avf->pb, sbg->max_file_size, &bprint);
if (r < 0) if (r < 0)
goto fail; goto fail2;
r = parse_script(avf, buf, r, &script);
r = parse_script(avf, bprint.str, bprint.len, &script);
if (r < 0) if (r < 0)
goto fail; goto fail2;
if (!sbg->sample_rate) if (!sbg->sample_rate)
sbg->sample_rate = script.sample_rate; sbg->sample_rate = script.sample_rate;
else else
@ -1431,8 +1417,8 @@ static av_cold int sbg_read_header(AVFormatContext *avf)
"-m is ignored and mix channels will be silent.\n"); "-m is ignored and mix channels will be silent.\n");
r = expand_script(avf, &script); r = expand_script(avf, &script);
if (r < 0) if (r < 0)
goto fail; goto fail2;
av_freep(&buf); av_bprint_finalize(&bprint, NULL);
r = generate_intervals(avf, &script, sbg->sample_rate, &inter); r = generate_intervals(avf, &script, sbg->sample_rate, &inter);
if (r < 0) if (r < 0)
goto fail; goto fail;
@ -1467,10 +1453,11 @@ static av_cold int sbg_read_header(AVFormatContext *avf)
free_script(&script); free_script(&script);
return 0; return 0;
fail2:
av_bprint_finalize(&bprint, NULL);
fail: fail:
av_free(inter.inter); av_free(inter.inter);
free_script(&script); free_script(&script);
av_free(buf);
return r; return r;
} }