]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mpeg.c
avformat/http: escape unsafe URL path in HTTP request
[ffmpeg] / libavformat / mpeg.c
index 80983f8a815ec3950b9070bd504f7bc91e53d444..fad7c7fd552b10f9719a48a78612d583fff1f0c9 100644 (file)
@@ -713,12 +713,23 @@ static int vobsub_probe(const AVProbeData *p)
     return 0;
 }
 
+static int vobsub_read_close(AVFormatContext *s)
+{
+    VobSubDemuxContext *vobsub = s->priv_data;
+    int i;
+
+    for (i = 0; i < s->nb_streams; i++)
+        ff_subtitles_queue_clean(&vobsub->q[i]);
+    if (vobsub->sub_ctx)
+        avformat_close_input(&vobsub->sub_ctx);
+    return 0;
+}
+
 static int vobsub_read_header(AVFormatContext *s)
 {
     int i, ret = 0, header_parsed = 0, langidx = 0;
     VobSubDemuxContext *vobsub = s->priv_data;
     size_t fname_len;
-    char *header_str = NULL;
     AVBPrint header;
     int64_t delay = 0;
     AVStream *st = NULL;
@@ -731,8 +742,7 @@ static int vobsub_read_header(AVFormatContext *s)
         char *ext;
         vobsub->sub_name = av_strdup(s->url);
         if (!vobsub->sub_name) {
-            ret = AVERROR(ENOMEM);
-            goto end;
+            return AVERROR(ENOMEM);
         }
 
         fname_len = strlen(vobsub->sub_name);
@@ -740,24 +750,23 @@ static int vobsub_read_header(AVFormatContext *s)
         if (fname_len < 4 || *(ext - 1) != '.') {
             av_log(s, AV_LOG_ERROR, "The input index filename is too short "
                    "to guess the associated .SUB file\n");
-            ret = AVERROR_INVALIDDATA;
-            goto end;
+            return AVERROR_INVALIDDATA;
         }
         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);
     }
 
     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();
     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)
         goto end;
 
@@ -767,7 +776,6 @@ static int vobsub_read_header(AVFormatContext *s)
         goto end;
     }
 
-    av_bprint_init(&header, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE);
     while (!avio_feof(s->pb)) {
         char line[MAX_LINE_SIZE];
         int len = ff_get_line(s->pb, line, sizeof(line));
@@ -888,22 +896,21 @@ static int vobsub_read_header(AVFormatContext *s)
     }
 
     if (!av_bprint_is_complete(&header)) {
-        av_bprint_finalize(&header, NULL);
         ret = AVERROR(ENOMEM);
         goto end;
     }
-    av_bprint_finalize(&header, &header_str);
     for (i = 0; i < s->nb_streams; i++) {
         AVCodecParameters *par = s->streams[i]->codecpar;
         ret = ff_alloc_extradata(par, header.len);
         if (ret < 0) {
             goto end;
         }
-        memcpy(par->extradata, header_str, header.len);
+        memcpy(par->extradata, header.str, header.len);
     }
 end:
-
-    av_free(header_str);
+    if (ret < 0)
+        vobsub_read_close(s);
+    av_bprint_finalize(&header, NULL);
     return ret;
 }
 
@@ -913,7 +920,6 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
     FFDemuxSubtitlesQueue *q;
     AVIOContext *pb = vobsub->sub_ctx->pb;
     int ret, psize, total_read = 0, i;
-    AVPacket idx_pkt = { 0 };
 
     int64_t min_ts = INT64_MAX;
     int sid = 0;
@@ -928,24 +934,22 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
         }
     }
     q = &vobsub->q[sid];
-    ret = ff_subtitles_queue_read_packet(q, &idx_pkt);
+    /* The returned packet will have size zero,
+     * so that it can be directly used with av_grow_packet. */
+    ret = ff_subtitles_queue_read_packet(q, pkt);
     if (ret < 0)
         return ret;
 
     /* compute maximum packet size using the next packet position. This is
      * useful when the len in the header is non-sense */
     if (q->current_sub_idx < q->nb_subs) {
-        psize = q->subs[q->current_sub_idx].pos - idx_pkt.pos;
+        psize = q->subs[q->current_sub_idx].pos - pkt->pos;
     } else {
         int64_t fsize = avio_size(pb);
-        psize = fsize < 0 ? 0xffff : fsize - idx_pkt.pos;
+        psize = fsize < 0 ? 0xffff : fsize - pkt->pos;
     }
 
-    avio_seek(pb, idx_pkt.pos, SEEK_SET);
-
-    av_init_packet(pkt);
-    pkt->size = 0;
-    pkt->data = NULL;
+    avio_seek(pb, pkt->pos, SEEK_SET);
 
     do {
         int n, to_read, startcode;
@@ -969,7 +973,7 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
         total_read += pkt_size;
 
         /* the current chunk doesn't match the stream index (unlikely) */
-        if ((startcode & 0x1f) != s->streams[idx_pkt.stream_index]->id)
+        if ((startcode & 0x1f) != s->streams[pkt->stream_index]->id)
             break;
 
         ret = av_grow_packet(pkt, to_read);
@@ -981,16 +985,10 @@ static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
             pkt->size -= to_read - n;
     } while (total_read < psize);
 
-    pkt->pts = pkt->dts = idx_pkt.pts;
-    pkt->pos = idx_pkt.pos;
-    pkt->stream_index = idx_pkt.stream_index;
-
-    av_packet_unref(&idx_pkt);
     return 0;
 
 fail:
     av_packet_unref(pkt);
-    av_packet_unref(&idx_pkt);
     return ret;
 }
 
@@ -1027,18 +1025,6 @@ static int vobsub_read_seek(AVFormatContext *s, int stream_index,
                                    min_ts, ts, max_ts, flags);
 }
 
-static int vobsub_read_close(AVFormatContext *s)
-{
-    VobSubDemuxContext *vobsub = s->priv_data;
-    int i;
-
-    for (i = 0; i < s->nb_streams; i++)
-        ff_subtitles_queue_clean(&vobsub->q[i]);
-    if (vobsub->sub_ctx)
-        avformat_close_input(&vobsub->sub_ctx);
-    return 0;
-}
-
 static const AVOption options[] = {
     { "sub_name", "URI for .sub file", offsetof(VobSubDemuxContext, sub_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
     { NULL }