--- /dev/null
+Backports of
+
+From 46e17f0cb4a80b36755c84b8bf15731d3386c08f Mon Sep 17 00:00:00 2001
+From: kyslov <kyslov@google.com>
+Date: Fri, 4 Jan 2019 17:04:09 -0800
+Subject: [PATCH] Fix OOB memory access on fuzzed data
+
+From 0681cff1ad36b3ef8ec242f59b5a6c4234ccfb88 Mon Sep 17 00:00:00 2001
+From: James Zern <jzern@google.com>
+Date: Tue, 24 Jul 2018 21:36:50 -0700
+Subject: [PATCH] vp9: fix OOB read in decoder_peek_si_internal
+
+From f00890eecdf8365ea125ac16769a83aa6b68792d Mon Sep 17 00:00:00 2001
+From: James Zern <jzern@google.com>
+Date: Tue, 11 Dec 2018 18:06:20 -0800
+Subject: [PATCH] update libwebm to libwebm-1.0.0.27-352-g6ab9fcf
+
+From 34d54b04e98dd0bac32e9aab0fbda0bf501bc742 Mon Sep 17 00:00:00 2001
+From: James Zern <jzern@google.com>
+Date: Tue, 9 Apr 2019 18:37:44 -0700
+Subject: [PATCH] update libwebm to libwebm-1.0.0.27-358-gdbf1d10
+
+From 52add5896661d186dec284ed646a4b33b607d2c7 Mon Sep 17 00:00:00 2001
+From: Jerome Jiang <jianj@google.com>
+Date: Wed, 23 May 2018 15:43:00 -0700
+Subject: [PATCH] VP8: Fix use-after-free in postproc.
+
+to address CVE-2019-9232 CVE-2019-9325 CVE-2019-9371 CVE-2019-9433
+
+--- a/test/decode_api_test.cc
++++ b/test/decode_api_test.cc
+@@ -138,8 +138,30 @@ TEST(DecodeAPI, Vp9InvalidDecode) {
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
+ }
+
+-TEST(DecodeAPI, Vp9PeekSI) {
++void TestPeekInfo(const uint8_t *const data, uint32_t data_sz,
++ uint32_t peek_size) {
+ const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo;
++ // Verify behavior of vpx_codec_decode. vpx_codec_decode doesn't even get
++ // to decoder_peek_si_internal on frames of size < 8.
++ if (data_sz >= 8) {
++ vpx_codec_ctx_t dec;
++ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0));
++ EXPECT_EQ((data_sz < peek_size) ? VPX_CODEC_UNSUP_BITSTREAM
++ : VPX_CODEC_CORRUPT_FRAME,
++ vpx_codec_decode(&dec, data, data_sz, NULL, 0));
++ vpx_codec_iter_t iter = NULL;
++ EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter));
++ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
++ }
++
++ // Verify behavior of vpx_codec_peek_stream_info.
++ vpx_codec_stream_info_t si;
++ si.sz = sizeof(si);
++ EXPECT_EQ((data_sz < peek_size) ? VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_OK,
++ vpx_codec_peek_stream_info(codec, data, data_sz, &si));
++}
++
++TEST(DecodeAPI, Vp9PeekStreamInfo) {
+ // The first 9 bytes are valid and the rest of the bytes are made up. Until
+ // size 10, this should return VPX_CODEC_UNSUP_BITSTREAM and after that it
+ // should return VPX_CODEC_CORRUPT_FRAME.
+@@ -150,24 +172,18 @@ TEST(DecodeAPI, Vp9PeekSI) {
+ };
+
+ for (uint32_t data_sz = 1; data_sz <= 32; ++data_sz) {
+- // Verify behavior of vpx_codec_decode. vpx_codec_decode doesn't even get
+- // to decoder_peek_si_internal on frames of size < 8.
+- if (data_sz >= 8) {
+- vpx_codec_ctx_t dec;
+- EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0));
+- EXPECT_EQ(
+- (data_sz < 10) ? VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_CORRUPT_FRAME,
+- vpx_codec_decode(&dec, data, data_sz, NULL, 0));
+- vpx_codec_iter_t iter = NULL;
+- EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter));
+- EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
+- }
+-
+- // Verify behavior of vpx_codec_peek_stream_info.
+- vpx_codec_stream_info_t si;
+- si.sz = sizeof(si);
+- EXPECT_EQ((data_sz < 10) ? VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_OK,
+- vpx_codec_peek_stream_info(codec, data, data_sz, &si));
++ TestPeekInfo(data, data_sz, 10);
++ }
++}
++
++TEST(DecodeAPI, Vp9PeekStreamInfoTruncated) {
++ // This profile 1 header requires 10.25 bytes, ensure
++ // vpx_codec_peek_stream_info doesn't over read.
++ const uint8_t profile1_data[10] = { 0xa4, 0xe9, 0x30, 0x68, 0x53,
++ 0xe9, 0x30, 0x68, 0x53, 0x04 };
++
++ for (uint32_t data_sz = 1; data_sz <= 10; ++data_sz) {
++ TestPeekInfo(profile1_data, data_sz, 11);
+ }
+ }
+ #endif // CONFIG_VP9_DECODER
+--- a/third_party/libwebm/mkvparser/mkvparser.cc
++++ b/third_party/libwebm/mkvparser/mkvparser.cc
+@@ -5307,8 +5307,8 @@ long VideoTrack::Parse(Segment* pSegment
+
+ const long long stop = pos + s.size;
+
+- Colour* colour = NULL;
+- Projection* projection = NULL;
++ std::unique_ptr<Colour> colour_ptr;
++ std::unique_ptr<Projection> projection_ptr;
+
+ while (pos < stop) {
+ long long id, size;
+@@ -5357,11 +5357,19 @@ long VideoTrack::Parse(Segment* pSegment
+ if (rate <= 0)
+ return E_FILE_FORMAT_INVALID;
+ } else if (id == libwebm::kMkvColour) {
+- if (!Colour::Parse(pReader, pos, size, &colour))
++ Colour* colour = NULL;
++ if (!Colour::Parse(pReader, pos, size, &colour)) {
+ return E_FILE_FORMAT_INVALID;
++ } else {
++ colour_ptr.reset(colour);
++ }
+ } else if (id == libwebm::kMkvProjection) {
+- if (!Projection::Parse(pReader, pos, size, &projection))
++ Projection* projection = NULL;
++ if (!Projection::Parse(pReader, pos, size, &projection)) {
+ return E_FILE_FORMAT_INVALID;
++ } else {
++ projection_ptr.reset(projection);
++ }
+ }
+
+ pos += size; // consume payload
+@@ -5392,8 +5400,8 @@ long VideoTrack::Parse(Segment* pSegment
+ pTrack->m_display_unit = display_unit;
+ pTrack->m_stereo_mode = stereo_mode;
+ pTrack->m_rate = rate;
+- pTrack->m_colour = colour;
+- pTrack->m_projection = projection;
++ pTrack->m_colour = colour_ptr.release();
++ pTrack->m_projection = projection_ptr.release();
+
+ pResult = pTrack;
+ return 0; // success
+--- a/vp8/common/postproc.c
++++ b/vp8/common/postproc.c
+@@ -65,7 +65,7 @@ void vp8_deblock(VP8_COMMON *cm, YV12_BU
+ double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
+ int ppl = (int)(level + .5);
+
+- const MODE_INFO *mode_info_context = cm->show_frame_mi;
++ const MODE_INFO *mode_info_context = cm->mi;
+ int mbr, mbc;
+
+ /* The pixel thresholds are adjusted according to if or not the macroblock
+--- a/vp8/decoder/dboolhuff.h
++++ b/vp8/decoder/dboolhuff.h
+@@ -76,7 +76,7 @@ static int vp8dx_decode_bool(BOOL_DECODE
+ }
+
+ {
+- register int shift = vp8_norm[range];
++ const unsigned char shift = vp8_norm[(unsigned char)range];
+ range <<= shift;
+ value <<= shift;
+ count -= shift;
+--- a/vp9/vp9_dx_iface.c
++++ b/vp9/vp9_dx_iface.c
+@@ -97,7 +97,7 @@ static vpx_codec_err_t decoder_peek_si_i
+ const uint8_t *data, unsigned int data_sz, vpx_codec_stream_info_t *si,
+ int *is_intra_only, vpx_decrypt_cb decrypt_cb, void *decrypt_state) {
+ int intra_only_flag = 0;
+- uint8_t clear_buffer[10];
++ uint8_t clear_buffer[11];
+
+ if (data + data_sz <= data) return VPX_CODEC_INVALID_PARAM;
+
+@@ -158,6 +158,9 @@ static vpx_codec_err_t decoder_peek_si_i
+ if (profile > PROFILE_0) {
+ if (!parse_bitdepth_colorspace_sampling(profile, &rb))
+ return VPX_CODEC_UNSUP_BITSTREAM;
++ // The colorspace info may cause vp9_read_frame_size() to need 11
++ // bytes.
++ if (data_sz < 11) return VPX_CODEC_UNSUP_BITSTREAM;
+ }
+ rb.bit_offset += REF_FRAMES; // refresh_frame_flags
+ vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
+--- a/vpx_dsp/bitreader.h
++++ b/vpx_dsp/bitreader.h
+@@ -94,7 +94,7 @@ static INLINE int vpx_read(vpx_reader *r
+ }
+
+ {
+- register int shift = vpx_norm[range];
++ const unsigned char shift = vpx_norm[(unsigned char)range];
+ range <<= shift;
+ value <<= shift;
+ count -= shift;
+--- a/vpx_dsp/bitreader_buffer.c
++++ b/vpx_dsp/bitreader_buffer.c
+@@ -23,7 +23,7 @@ int vpx_rb_read_bit(struct vpx_read_bit_
+ rb->bit_offset = off + 1;
+ return bit;
+ } else {
+- rb->error_handler(rb->error_handler_data);
++ if (rb->error_handler != NULL) rb->error_handler(rb->error_handler_data);
+ return 0;
+ }
+ }