aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@gmail.com>2021-03-24 04:41:58 +0100
committerAndreas Rheinhardt <andreas.rheinhardt@gmail.com>2021-03-26 03:03:59 +0100
commit05457a3661371f7248b5602bf96c5011ab0b0d25 (patch)
tree2837812fdc6ca1239eb618d201987088ee40d604
parent3ec3370deac4d21538ef03d8547a12f3acb7bfa8 (diff)
downloadffmpeg-05457a3661371f7248b5602bf96c5011ab0b0d25.tar.gz
avformat/libgme: Fix memleaks on errors
Also free the gme_info_t structure immediately after its use. This simplifies cleanup, because it might be unsafe to call gme_free_info(NULL) (or even worse, gme_track_info() might even on error set the pointer to the gme_info_t structure to something else than NULL). Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
-rw-r--r--libavformat/libgme.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/libavformat/libgme.c b/libavformat/libgme.c
index e6c56c4872..f9d9abaad5 100644
--- a/libavformat/libgme.c
+++ b/libavformat/libgme.c
@@ -31,7 +31,6 @@
typedef struct GMEContext {
const AVClass *class;
Music_Emu *music_emu;
- gme_info_t *info; ///< selected track
/* options */
int track_index;
@@ -55,12 +54,16 @@ static void add_meta(AVFormatContext *s, const char *name, const char *value)
av_dict_set(&s->metadata, name, value, 0);
}
-static int load_metadata(AVFormatContext *s)
+static int load_metadata(AVFormatContext *s, int64_t *duration)
{
GMEContext *gme = s->priv_data;
- gme_info_t *info = gme->info;
+ gme_info_t *info = NULL;
char buf[30];
+ if (gme_track_info(gme->music_emu, &info, gme->track_index))
+ return AVERROR_STREAM_NOT_FOUND;
+
+ *duration = info->length;
add_meta(s, "system", info->system);
add_meta(s, "game", info->game);
add_meta(s, "song", info->song);
@@ -71,20 +74,30 @@ static int load_metadata(AVFormatContext *s)
snprintf(buf, sizeof(buf), "%d", (int)gme_track_count(gme->music_emu));
add_meta(s, "tracks", buf);
+ gme_free_info(info);
return 0;
}
#define AUDIO_PKT_SIZE 512
+static int read_close_gme(AVFormatContext *s)
+{
+ GMEContext *gme = s->priv_data;
+ gme_delete(gme->music_emu);
+ return 0;
+}
+
static int read_header_gme(AVFormatContext *s)
{
AVStream *st;
AVIOContext *pb = s->pb;
GMEContext *gme = s->priv_data;
int64_t sz = avio_size(pb);
+ int64_t duration;
char *buf;
char dummy;
+ int ret;
if (sz < 0) {
av_log(s, AV_LOG_WARNING, "Could not determine file size\n");
@@ -103,6 +116,7 @@ static int read_header_gme(AVFormatContext *s)
av_log(s, AV_LOG_ERROR, "File size is larger than max_size option "
"value %"PRIi64", consider increasing the max_size option\n",
gme->max_size);
+ av_freep(&buf);
return AVERROR_BUFFER_TOO_SMALL;
}
@@ -112,20 +126,24 @@ static int read_header_gme(AVFormatContext *s)
}
av_freep(&buf);
- if (gme_track_info(gme->music_emu, &gme->info, gme->track_index))
- return AVERROR_STREAM_NOT_FOUND;
-
- if (gme_start_track(gme->music_emu, gme->track_index))
+ ret = load_metadata(s, &duration);
+ if (ret < 0) {
+ read_close_gme(s);
+ return ret;
+ }
+ if (gme_start_track(gme->music_emu, gme->track_index)) {
+ read_close_gme(s);
return AVERROR_UNKNOWN;
-
- load_metadata(s);
+ }
st = avformat_new_stream(s, NULL);
- if (!st)
+ if (!st) {
+ read_close_gme(s);
return AVERROR(ENOMEM);
+ }
avpriv_set_pts_info(st, 64, 1, 1000);
if (st->duration > 0)
- st->duration = gme->info->length;
+ st->duration = duration;
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE);
st->codecpar->channels = 2;
@@ -153,14 +171,6 @@ static int read_packet_gme(AVFormatContext *s, AVPacket *pkt)
return 0;
}
-static int read_close_gme(AVFormatContext *s)
-{
- GMEContext *gme = s->priv_data;
- gme_free_info(gme->info);
- gme_delete(gme->music_emu);
- return 0;
-}
-
static int read_seek_gme(AVFormatContext *s, int stream_idx, int64_t ts, int flags)
{
GMEContext *gme = s->priv_data;