Browse code

avformat: Add and use ff_copy_whitelists()

Fixes potential security issue in case of running out of memory

Found-by: ubitux
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2014/10/25 02:23:23
Showing 9 changed files
... ...
@@ -1040,9 +1040,8 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
1040 1040
 
1041 1041
         ast->sub_ctx->pb = pb;
1042 1042
 
1043
-        av_assert0(!ast->sub_ctx->codec_whitelist && !ast->sub_ctx->format_whitelist);
1044
-        ast->sub_ctx-> codec_whitelist = av_strdup(s->codec_whitelist);
1045
-        ast->sub_ctx->format_whitelist = av_strdup(s->format_whitelist);
1043
+        if (ff_copy_whitelists(ast->sub_ctx, s) < 0)
1044
+            goto error;
1046 1045
 
1047 1046
         if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) {
1048 1047
             ff_read_packet(ast->sub_ctx, &ast->sub_pkt);
... ...
@@ -1056,6 +1055,7 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
1056 1056
         return 1;
1057 1057
 
1058 1058
 error:
1059
+        av_freep(&ast->sub_ctx);
1059 1060
         av_freep(&pb);
1060 1061
     }
1061 1062
     return 0;
... ...
@@ -289,9 +289,8 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
289 289
 
290 290
     cat->avf->interrupt_callback = avf->interrupt_callback;
291 291
 
292
-    av_assert0(!cat->avf->codec_whitelist && !cat->avf->format_whitelist);
293
-    cat->avf-> codec_whitelist = av_strdup(avf->codec_whitelist);
294
-    cat->avf->format_whitelist = av_strdup(avf->format_whitelist);
292
+    if ((ret = ff_copy_whitelists(cat->avf, avf)) < 0)
293
+        return ret;
295 294
 
296 295
     if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 ||
297 296
         (ret = avformat_find_stream_info(cat->avf, NULL)) < 0) {
... ...
@@ -1345,9 +1345,8 @@ static int hls_read_header(AVFormatContext *s)
1345 1345
         pls->ctx->pb       = &pls->pb;
1346 1346
         pls->stream_offset = stream_offset;
1347 1347
 
1348
-        av_assert0(!pls->ctx->codec_whitelist && !pls->ctx->format_whitelist);
1349
-        pls->ctx-> codec_whitelist = av_strdup(s->codec_whitelist);
1350
-        pls->ctx->format_whitelist = av_strdup(s->format_whitelist);
1348
+        if ((ret = ff_copy_whitelists(pls->ctx, s)) < 0)
1349
+            goto fail;
1351 1350
 
1352 1351
         ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL);
1353 1352
         if (ret < 0)
... ...
@@ -412,5 +412,9 @@ enum AVWriteUncodedFrameFlags {
412 412
 
413 413
 };
414 414
 
415
+/**
416
+ * Copies the whilelists from one context to the other
417
+ */
418
+int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src);
415 419
 
416 420
 #endif /* AVFORMAT_INTERNAL_H */
... ...
@@ -76,9 +76,8 @@ static int libquvi_read_header(AVFormatContext *s)
76 76
     if (rc != QUVI_OK)
77 77
         goto quvi_fail;
78 78
 
79
-    av_assert0(!qc->fmtctx->codec_whitelist && !qc->fmtctx->format_whitelist);
80
-    qc->fmtctx-> codec_whitelist = av_strdup(s->codec_whitelist);
81
-    qc->fmtctx->format_whitelist = av_strdup(s->format_whitelist);
79
+    if ((ret = ff_copy_whitelists(qc->fmtctx, s)) < 0)
80
+        goto end;
82 81
 
83 82
     ret = avformat_open_input(&qc->fmtctx, media_url, NULL, NULL);
84 83
     if (ret < 0)
... ...
@@ -700,8 +700,8 @@ static int vobsub_read_header(AVFormatContext *s)
700 700
     if (!vobsub->sub_ctx)
701 701
         return AVERROR(ENOMEM);
702 702
 
703
-    vobsub->sub_ctx-> codec_whitelist = av_strdup(s->codec_whitelist);
704
-    vobsub->sub_ctx->format_whitelist = av_strdup(s->format_whitelist);
703
+    if ((ret = ff_copy_whitelists(vobsub->sub_ctx, s)) < 0)
704
+        goto end;
705 705
 
706 706
     ret = avformat_open_input(&vobsub->sub_ctx, sub_name, &ff_mpegps_demuxer, NULL);
707 707
     if (ret < 0) {
... ...
@@ -117,9 +117,10 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
117 117
         rt->asf_ctx->pb      = &pb;
118 118
         av_dict_set(&opts, "no_resync_search", "1", 0);
119 119
 
120
-        av_assert0(!rt->asf_ctx->codec_whitelist && !rt->asf_ctx->format_whitelist);
121
-        rt->asf_ctx-> codec_whitelist = av_strdup(s->codec_whitelist);
122
-        rt->asf_ctx->format_whitelist = av_strdup(s->format_whitelist);
120
+        if ((ret = ff_copy_whitelists(rt->asf_ctx, s)) < 0) {
121
+            av_dict_free(&opts);
122
+            return ret;
123
+        }
123 124
 
124 125
         ret = avformat_open_input(&rt->asf_ctx, "", &ff_asf_demuxer, &opts);
125 126
         av_dict_free(&opts);
... ...
@@ -160,9 +160,8 @@ static int sap_read_header(AVFormatContext *s)
160 160
     sap->sdp_ctx->pb        = &sap->sdp_pb;
161 161
     sap->sdp_ctx->interrupt_callback = s->interrupt_callback;
162 162
 
163
-    av_assert0(!sap->sdp_ctx->codec_whitelist && !sap->sdp_ctx->format_whitelist);
164
-    sap->sdp_ctx-> codec_whitelist = av_strdup(s->codec_whitelist);
165
-    sap->sdp_ctx->format_whitelist = av_strdup(s->format_whitelist);
163
+    if ((ret = ff_copy_whitelists(sap->sdp_ctx, s)) < 0)
164
+        goto fail;
166 165
 
167 166
     ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
168 167
     if (ret < 0)
... ...
@@ -130,6 +130,19 @@ void av_format_inject_global_side_data(AVFormatContext *s)
130 130
     }
131 131
 }
132 132
 
133
+int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src)
134
+{
135
+    av_assert0(!dst->codec_whitelist && !dst->format_whitelist);
136
+    dst-> codec_whitelist = av_strdup(src->codec_whitelist);
137
+    dst->format_whitelist = av_strdup(src->format_whitelist);
138
+    if (   (src-> codec_whitelist && !dst-> codec_whitelist)
139
+        || (src->format_whitelist && !dst->format_whitelist)) {
140
+        av_log(dst, AV_LOG_ERROR, "Failed to duplicate whitelist\n");
141
+        return AVERROR(ENOMEM);
142
+    }
143
+    return 0;
144
+}
145
+
133 146
 static const AVCodec *find_decoder(AVFormatContext *s, AVStream *st, enum AVCodecID codec_id)
134 147
 {
135 148
     if (st->codec->codec)