From 549985eefe5f6f597db6ef2f7ed52376d90b154f Mon Sep 17 00:00:00 2001
From: philippegorley <philippe.gorley@savoirfairelinux.com>
Date: Mon, 25 Sep 2017 13:40:05 -0400
Subject: [PATCH] media: fix mismatched free and double free

FFmpeg frees and reallocs the buffer multiple times internally, which
means 2 things:
1. Mismatched free, as std::vector uses new, FFmpeg uses free.
2. buf_ no longer points to the correct address by the time it goes out
of scope; it points to an already freed part of memory.

Use a local variable instead of a class member to store the initial
buffer.

Change-Id: Ibe98658e68bec1b69875e6679ba1319dd7d98706
Reviewed-by: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
---
 src/media/media_io_handle.cpp | 14 +++++++++++---
 src/media/media_io_handle.h   |  1 -
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/media/media_io_handle.cpp b/src/media/media_io_handle.cpp
index d276380266..9e56114a76 100644
--- a/src/media/media_io_handle.cpp
+++ b/src/media/media_io_handle.cpp
@@ -31,12 +31,20 @@ MediaIOHandle::MediaIOHandle(std::size_t buffer_size,
                              void *opaque) : ctx_(0)
 
 {
-    buf_.reserve(buffer_size);
-    ctx_ = avio_alloc_context(buf_.data(), buffer_size, writeable, opaque, read_cb,
+    /* FFmpeg doesn't alloc the buffer for the first time, but it does free and
+     * alloc it afterwards.
+     * Don't directly use malloc because av_malloc is optimized for memory alignment.
+     */
+    auto buf = static_cast<uint8_t*>(av_malloc(buffer_size));
+    ctx_ = avio_alloc_context(buf, buffer_size, writeable, opaque, read_cb,
                               write_cb, seek_cb);
     ctx_->max_packet_size = buffer_size;
 }
 
-MediaIOHandle::~MediaIOHandle() { av_free(ctx_); }
+MediaIOHandle::~MediaIOHandle()
+{
+    av_free(ctx_->buffer);
+    av_free(ctx_);
+}
 
 } // namespace ring
diff --git a/src/media/media_io_handle.h b/src/media/media_io_handle.h
index 82f06c806a..ce68cb1ea7 100644
--- a/src/media/media_io_handle.h
+++ b/src/media/media_io_handle.h
@@ -52,7 +52,6 @@ public:
 private:
     NON_COPYABLE(MediaIOHandle);
     AVIOContext *ctx_;
-    std::vector<uint8_t> buf_ {};
 };
 
 } // namespace ring
-- 
GitLab