]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/aviobuf.c
avformat/avidec: Avoid integer overflow in NI switch check
[ffmpeg] / libavformat / aviobuf.c
index 5a33f82950c32b2a1dee172ce4c61ed97469c51e..cc22beff285a3accada66f38a93eb0f9eb65768a 100644 (file)
  */
 #define SHORT_SEEK_THRESHOLD 4096
 
-typedef struct AVIOInternal {
-    URLContext *h;
-} AVIOInternal;
-
 static void *ff_avio_child_next(void *obj, void *prev)
 {
     AVIOContext *s = obj;
-    AVIOInternal *internal = s->opaque;
-    return prev ? NULL : internal->h;
+    return prev ? NULL : s->opaque;
 }
 
 static const AVClass *ff_avio_child_class_next(const AVClass *prev)
@@ -255,6 +250,9 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
     if(!s)
         return AVERROR(EINVAL);
 
+    if ((whence & AVSEEK_SIZE))
+        return s->seek ? s->seek(s->opaque, offset, AVSEEK_SIZE) : AVERROR(ENOSYS);
+
     buffer_size = s->buf_end - s->buffer;
     // pos is the absolute position that the beginning of s->buffer corresponds to in the file
     pos = s->pos - (s->write_flag ? 0 : buffer_size);
@@ -570,7 +568,7 @@ static void fill_buffer(AVIOContext *s)
     }
 
     /* make buffer smaller in case it ended up large after probing */
-    if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size) {
+    if (s->read_packet && s->orig_buffer_size && s->buffer_size > s->orig_buffer_size && len >= s->orig_buffer_size) {
         if (dst == s->buffer && s->buf_ptr != dst) {
             int ret = ffio_set_buf_size(s, s->orig_buffer_size);
             if (ret < 0)
@@ -578,7 +576,6 @@ static void fill_buffer(AVIOContext *s)
 
             s->checksum_ptr = dst = s->buffer;
         }
-        av_assert0(len >= s->orig_buffer_size);
         len = s->orig_buffer_size;
     }
 
@@ -938,49 +935,8 @@ uint64_t ffio_read_varlen(AVIOContext *bc){
     return val;
 }
 
-static int io_read_packet(void *opaque, uint8_t *buf, int buf_size)
-{
-    AVIOInternal *internal = opaque;
-    return ffurl_read(internal->h, buf, buf_size);
-}
-
-static int io_write_packet(void *opaque, uint8_t *buf, int buf_size)
-{
-    AVIOInternal *internal = opaque;
-    return ffurl_write(internal->h, buf, buf_size);
-}
-
-static int64_t io_seek(void *opaque, int64_t offset, int whence)
-{
-    AVIOInternal *internal = opaque;
-    return ffurl_seek(internal->h, offset, whence);
-}
-
-static int io_short_seek(void *opaque)
-{
-    AVIOInternal *internal = opaque;
-    return ffurl_get_short_seek(internal->h);
-}
-
-static int io_read_pause(void *opaque, int pause)
-{
-    AVIOInternal *internal = opaque;
-    if (!internal->h->prot->url_read_pause)
-        return AVERROR(ENOSYS);
-    return internal->h->prot->url_read_pause(internal->h, pause);
-}
-
-static int64_t io_read_seek(void *opaque, int stream_index, int64_t timestamp, int flags)
-{
-    AVIOInternal *internal = opaque;
-    if (!internal->h->prot->url_read_seek)
-        return AVERROR(ENOSYS);
-    return internal->h->prot->url_read_seek(internal->h, stream_index, timestamp, flags);
-}
-
 int ffio_fdopen(AVIOContext **s, URLContext *h)
 {
-    AVIOInternal *internal = NULL;
     uint8_t *buffer = NULL;
     int buffer_size, max_packet_size;
 
@@ -994,14 +950,10 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
     if (!buffer)
         return AVERROR(ENOMEM);
 
-    internal = av_mallocz(sizeof(*internal));
-    if (!internal)
-        goto fail;
-
-    internal->h = h;
-
-    *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE,
-                            internal, io_read_packet, io_write_packet, io_seek);
+    *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,
+                            (int (*)(void *, uint8_t *, int))  ffurl_read,
+                            (int (*)(void *, uint8_t *, int))  ffurl_write,
+                            (int64_t (*)(void *, int64_t, int))ffurl_seek);
     if (!*s)
         goto fail;
 
@@ -1021,30 +973,28 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
     (*s)->max_packet_size = max_packet_size;
     (*s)->min_packet_size = h->min_packet_size;
     if(h->prot) {
-        (*s)->read_pause = io_read_pause;
-        (*s)->read_seek  = io_read_seek;
+        (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
+        (*s)->read_seek  =
+            (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
 
         if (h->prot->url_read_seek)
             (*s)->seekable |= AVIO_SEEKABLE_TIME;
     }
-    (*s)->short_seek_get = io_short_seek;
+    (*s)->short_seek_get = (int (*)(void *))ffurl_get_short_seek;
     (*s)->av_class = &ff_avio_class;
     return 0;
 fail:
-    av_freep(&internal);
     av_freep(&buffer);
     return AVERROR(ENOMEM);
 }
 
 URLContext* ffio_geturlcontext(AVIOContext *s)
 {
-    AVIOInternal *internal;
     if (!s)
         return NULL;
 
-    internal = s->opaque;
-    if (internal && s->read_packet == io_read_packet)
-        return internal->h;
+    if (s->opaque && s->read_packet == (int (*)(void *, uint8_t *, int))ffurl_read)
+        return s->opaque;
     else
         return NULL;
 }
@@ -1094,6 +1044,37 @@ int ffio_set_buf_size(AVIOContext *s, int buf_size)
     return 0;
 }
 
+int ffio_realloc_buf(AVIOContext *s, int buf_size)
+{
+    uint8_t *buffer;
+    int data_size;
+
+    if (!s->buffer_size)
+        return ffio_set_buf_size(s, buf_size);
+
+    if (buf_size <= s->buffer_size)
+        return 0;
+
+    buffer = av_malloc(buf_size);
+    if (!buffer)
+        return AVERROR(ENOMEM);
+
+    data_size = s->write_flag ? (s->buf_ptr - s->buffer) : (s->buf_end - s->buf_ptr);
+    if (data_size > 0)
+        memcpy(buffer, s->write_flag ? s->buffer : s->buf_ptr, data_size);
+    av_free(s->buffer);
+    s->buffer = buffer;
+    s->orig_buffer_size = buf_size;
+    s->buffer_size = buf_size;
+    s->buf_ptr = s->write_flag ? (s->buffer + data_size) : s->buffer;
+    if (s->write_flag)
+        s->buf_ptr_max = s->buffer + data_size;
+
+    s->buf_end = s->write_flag ? (s->buffer + s->buffer_size) : (s->buf_ptr + data_size);
+
+    return 0;
+}
+
 static int url_resetbuf(AVIOContext *s, int flags)
 {
     av_assert1(flags == AVIO_FLAG_WRITE || flags == AVIO_FLAG_READ);
@@ -1164,6 +1145,8 @@ int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
     URLContext *h;
     int err;
 
+    *s = NULL;
+
     err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL);
     if (err < 0)
         return err;
@@ -1181,25 +1164,17 @@ int avio_open2(AVIOContext **s, const char *filename, int flags,
     return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL, NULL);
 }
 
-int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
-                       const AVIOInterruptCB *int_cb, AVDictionary **options)
-{
-    return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist, s->protocol_blacklist);
-}
-
 int avio_close(AVIOContext *s)
 {
-    AVIOInternal *internal;
     URLContext *h;
 
     if (!s)
         return 0;
 
     avio_flush(s);
-    internal = s->opaque;
-    h        = internal->h;
+    h         = s->opaque;
+    s->opaque = NULL;
 
-    av_freep(&s->opaque);
     av_freep(&s->buffer);
     if (s->write_flag)
         av_log(s, AV_LOG_VERBOSE, "Statistics: %d seeks, %d writeouts\n", s->seek_count, s->writeout_count);
@@ -1222,14 +1197,26 @@ int avio_closep(AVIOContext **s)
 int avio_printf(AVIOContext *s, const char *fmt, ...)
 {
     va_list ap;
-    char buf[4096]; /* update doc entry in avio.h if changed */
-    int ret;
+    AVBPrint bp;
 
+    av_bprint_init(&bp, 0, INT_MAX);
     va_start(ap, fmt);
-    ret = vsnprintf(buf, sizeof(buf), fmt, ap);
+    av_vbprintf(&bp, fmt, ap);
     va_end(ap);
-    avio_write(s, buf, strlen(buf));
-    return ret;
+    if (!av_bprint_is_complete(&bp)) {
+        av_bprint_finalize(&bp, NULL);
+        s->error = AVERROR(ENOMEM);
+        return AVERROR(ENOMEM);
+    }
+    avio_write(s, bp.str, bp.len);
+    av_bprint_finalize(&bp, NULL);
+    return bp.len;
+}
+
+void avio_print_string_array(AVIOContext *s, const char *strings[])
+{
+    for(; *strings; strings++)
+        avio_write(s, (const unsigned char *)*strings, strlen(*strings));
 }
 
 int avio_pause(AVIOContext *s, int pause)
@@ -1279,8 +1266,7 @@ int avio_read_to_bprint(AVIOContext *h, AVBPrint *pb, size_t max_size)
 int avio_accept(AVIOContext *s, AVIOContext **c)
 {
     int ret;
-    AVIOInternal *internal = s->opaque;
-    URLContext *sc = internal->h;
+    URLContext *sc = s->opaque;
     URLContext *cc = NULL;
     ret = ffurl_accept(sc, &cc);
     if (ret < 0)
@@ -1290,8 +1276,7 @@ int avio_accept(AVIOContext *s, AVIOContext **c)
 
 int avio_handshake(AVIOContext *c)
 {
-    AVIOInternal *internal = c->opaque;
-    URLContext *cc = internal->h;
+    URLContext *cc = c->opaque;
     return ffurl_handshake(cc);
 }
 
@@ -1404,14 +1389,19 @@ int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
 {
     DynBuffer *d;
 
-    if (!s) {
+    if (!s || s->error) {
         *pbuffer = NULL;
         return 0;
     }
+    d = s->opaque;
+
+    if (!d->size) {
+        *pbuffer = d->io_buffer;
+        return FFMAX(s->buf_ptr, s->buf_ptr_max) - s->buffer;
+    }
 
     avio_flush(s);
 
-    d = s->opaque;
     *pbuffer = d->buffer;
 
     return d->size;
@@ -1449,12 +1439,15 @@ int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
 
 void ffio_free_dyn_buf(AVIOContext **s)
 {
-    uint8_t *tmp;
+    DynBuffer *d;
+
     if (!*s)
         return;
-    avio_close_dyn_buf(*s, &tmp);
-    av_free(tmp);
-    *s = NULL;
+
+    d = (*s)->opaque;
+    av_free(d->buffer);
+    av_free(d);
+    avio_context_free(s);
 }
 
 static int null_buf_write(void *opaque, uint8_t *buf, int buf_size)