Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(304)

Unified Diff: media/filters/skcanvas_video_renderer.cc

Issue 624633002: Fix potential use-after-free bug in VideoImageGenerator::onGetYUV8Planes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/skcanvas_video_renderer.cc
diff --git a/media/filters/skcanvas_video_renderer.cc b/media/filters/skcanvas_video_renderer.cc
index 9bdd393e56c31c368b926de08be9e4e42a993382..752dfffa862ecaf73fe1975aba1b098d6d1c9701 100644
--- a/media/filters/skcanvas_video_renderer.cc
+++ b/media/filters/skcanvas_video_renderer.cc
@@ -208,10 +208,13 @@ static void ConvertVideoFrameToRGBPixels(
// Generates an RGB image from a VideoFrame.
class VideoImageGenerator : public SkImageGenerator {
public:
- VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) : frame_(frame) {}
+ VideoImageGenerator(const scoped_refptr<VideoFrame>& frame) : frame_(frame) {
+ DCHECK(frame_.get());
+ }
virtual ~VideoImageGenerator() {}
-
- void set_frame(const scoped_refptr<VideoFrame>& frame) { frame_ = frame; }
+ void discard_frame() {
+ frame_ = NULL;
+ }
protected:
virtual bool onGetInfo(SkImageInfo* info) OVERRIDE {
@@ -227,13 +230,12 @@ class VideoImageGenerator : public SkImageGenerator {
size_t row_bytes,
SkPMColor ctable[],
int* ctable_count) OVERRIDE {
- if (!frame_.get())
- return false;
+ // This method should be called only one time.
+ DCHECK(frame_.get());
if (!pixels)
- return true;
+ return false;
// If skia couldn't do the YUV conversion, we will.
ConvertVideoFrameToRGBPixels(frame_, pixels, row_bytes);
- frame_ = NULL;
return true;
}
@@ -243,6 +245,11 @@ class VideoImageGenerator : public SkImageGenerator {
SkYUVColorSpace* color_space) OVERRIDE {
if (!frame_.get() || !IsYUV(frame_->format()))
return false;
+#if DCHECK_IS_ON
+ // This method should be called to get a YUV plane only one time.
+ if (row_bytes && planes)
+ DCHECK(frame_.get());
+#endif
if (color_space) {
if (IsJPEGColorSpace(frame_->format()))
@@ -278,8 +285,6 @@ class VideoImageGenerator : public SkImageGenerator {
planes[plane] = frame_->data(plane) + offset;
dshwang 2014/10/02 18:23:52 It exposes VideoFrame's data to caller
}
}
- if (planes && row_bytes)
- frame_ = NULL;
dshwang 2014/10/02 18:23:52 Removing frame_ can cause seg fault. So I remove |
return true;
}
@@ -288,7 +293,7 @@ class VideoImageGenerator : public SkImageGenerator {
};
SkCanvasVideoRenderer::SkCanvasVideoRenderer()
- : generator_(NULL), last_frame_timestamp_(media::kNoTimestamp()) {
+ : last_frame_timestamp_(media::kNoTimestamp()) {
last_frame_.setIsVolatile(true);
}
@@ -318,13 +323,13 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
return;
}
+ VideoImageGenerator* generator = NULL;
// Check if we should convert and update |last_frame_|.
if (last_frame_.isNull() ||
video_frame->timestamp() != last_frame_timestamp_) {
- generator_ = new VideoImageGenerator(video_frame);
-
- // Note: This takes ownership of |generator_|.
- if (!SkInstallDiscardablePixelRef(generator_, &last_frame_)) {
+ generator = new VideoImageGenerator(video_frame);
+ // Note: This takes ownership of new VideoImageGenerator instance.
+ if (!SkInstallDiscardablePixelRef(generator, &last_frame_)) {
NOTREACHED();
}
@@ -347,15 +352,7 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
break;
}
- // We copied the frame into a new bitmap and threw out the old one, so we
- // no longer have a |generator_| around. This should be removed when the
- // above TODO is addressed.
- if (video_rotation != VIDEO_ROTATION_0)
- generator_ = NULL;
-
last_frame_timestamp_ = video_frame->timestamp();
- } else if (generator_) {
- generator_->set_frame(video_frame);
}
paint.setXfermodeMode(mode);
@@ -364,6 +361,10 @@ void SkCanvasVideoRenderer::Paint(const scoped_refptr<VideoFrame>& video_frame,
paint.setFilterLevel(SkPaint::kLow_FilterLevel);
canvas->drawBitmapRect(last_frame_, NULL, dest, &paint);
canvas->flush();
+ // SkCanvas::flush() causes the generator to generate SkImage, so delete
+ // |video_frame| not to be outlived.
+ if (generator)
+ generator->discard_frame();
dshwang 2014/10/09 19:59:57 This line caused use-after-free because SkCanvas::
dshwang 2014/10/10 14:13:55 It's wrong analysis. |generator| is deleted by rep
}
void SkCanvasVideoRenderer::Copy(const scoped_refptr<VideoFrame>& video_frame,
« no previous file with comments | « media/filters/skcanvas_video_renderer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698