Browse Source

avformat/mpeg: Don't copy or leak string in AVBPrint

vobsub_read_header() uses an AVBPrint to write a string and up until
now, it collected the string stored in the AVBPrint via
av_bprint_finalize(), which might involve an allocation and copy of the
string. But this is unnecessary, as the lifetime of the returned string
does not exceed the lifetime of the AVBPrint. So use the string in the
AVBPrint directly.

This also makes it possible to easily fix a memleak: In certain error
situations, the string stored in the AVBPrint would not be freed (if it
was dynamically allocated). This has been fixed, too.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
tags/n4.3
Andreas Rheinhardt Michael Niedermayer 6 years ago
parent
commit
bc3cf2bbd3
1 changed files with 8 additions and 14 deletions
  1. +8
    -14
      libavformat/mpeg.c

+ 8
- 14
libavformat/mpeg.c View File

@@ -718,7 +718,6 @@ static int vobsub_read_header(AVFormatContext *s)
int i, ret = 0, header_parsed = 0, langidx = 0; int i, ret = 0, header_parsed = 0, langidx = 0;
VobSubDemuxContext *vobsub = s->priv_data; VobSubDemuxContext *vobsub = s->priv_data;
size_t fname_len; size_t fname_len;
char *header_str = NULL;
AVBPrint header; AVBPrint header;
int64_t delay = 0; int64_t delay = 0;
AVStream *st = NULL; AVStream *st = NULL;
@@ -731,8 +730,7 @@ static int vobsub_read_header(AVFormatContext *s)
char *ext; char *ext;
vobsub->sub_name = av_strdup(s->url); vobsub->sub_name = av_strdup(s->url);
if (!vobsub->sub_name) { if (!vobsub->sub_name) {
ret = AVERROR(ENOMEM);
goto end;
return AVERROR(ENOMEM);
} }


fname_len = strlen(vobsub->sub_name); fname_len = strlen(vobsub->sub_name);
@@ -740,24 +738,23 @@ static int vobsub_read_header(AVFormatContext *s)
if (fname_len < 4 || *(ext - 1) != '.') { if (fname_len < 4 || *(ext - 1) != '.') {
av_log(s, AV_LOG_ERROR, "The input index filename is too short " av_log(s, AV_LOG_ERROR, "The input index filename is too short "
"to guess the associated .SUB file\n"); "to guess the associated .SUB file\n");
ret = AVERROR_INVALIDDATA;
goto end;
return AVERROR_INVALIDDATA;
} }
memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3); memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3);
av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->url, vobsub->sub_name); av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->url, vobsub->sub_name);
} }


if (!(iformat = av_find_input_format("mpeg"))) { if (!(iformat = av_find_input_format("mpeg"))) {
ret = AVERROR_DEMUXER_NOT_FOUND;
goto end;
return AVERROR_DEMUXER_NOT_FOUND;
} }


vobsub->sub_ctx = avformat_alloc_context(); vobsub->sub_ctx = avformat_alloc_context();
if (!vobsub->sub_ctx) { if (!vobsub->sub_ctx) {
ret = AVERROR(ENOMEM);
goto end;
return AVERROR(ENOMEM);
} }


av_bprint_init(&header, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE);

if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0) if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0)
goto end; goto end;


@@ -767,7 +764,6 @@ static int vobsub_read_header(AVFormatContext *s)
goto end; goto end;
} }


av_bprint_init(&header, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE);
while (!avio_feof(s->pb)) { while (!avio_feof(s->pb)) {
char line[MAX_LINE_SIZE]; char line[MAX_LINE_SIZE];
int len = ff_get_line(s->pb, line, sizeof(line)); int len = ff_get_line(s->pb, line, sizeof(line));
@@ -888,22 +884,20 @@ static int vobsub_read_header(AVFormatContext *s)
} }


if (!av_bprint_is_complete(&header)) { if (!av_bprint_is_complete(&header)) {
av_bprint_finalize(&header, NULL);
ret = AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
goto end; goto end;
} }
av_bprint_finalize(&header, &header_str);
for (i = 0; i < s->nb_streams; i++) { for (i = 0; i < s->nb_streams; i++) {
AVCodecParameters *par = s->streams[i]->codecpar; AVCodecParameters *par = s->streams[i]->codecpar;
ret = ff_alloc_extradata(par, header.len); ret = ff_alloc_extradata(par, header.len);
if (ret < 0) { if (ret < 0) {
goto end; goto end;
} }
memcpy(par->extradata, header_str, header.len);
memcpy(par->extradata, header.str, header.len);
} }
end: end:


av_free(header_str);
av_bprint_finalize(&header, NULL);
return ret; return ret;
} }




Loading…
Cancel
Save