vp8: Validate dimensions when setting reference frame

Modifty the vp8_set/get_reference to validate the
dimensions of the references match the dimensions
of the internal reference buffer.

Add unittest.

Bug: 526737981
Change-Id: I81c3ff470fce3f25c6e30c605ddf2a925d682f6a
diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc
index 21bc2e8..809ea8a 100644
--- a/test/encode_api_test.cc
+++ b/test/encode_api_test.cc
@@ -532,6 +532,44 @@
   vpx_codec_destroy(&enc);
 }
 
+// Bug: 526737981.
+TEST(EncodeAPI, SetReferenceSizeValidationVp8) {
+  vpx_codec_iface_t *const iface = vpx_codec_vp8_cx();
+  vpx_codec_enc_cfg_t cfg;
+  vpx_codec_ctx_t enc;
+  ASSERT_EQ(vpx_codec_enc_config_default(iface, &cfg, 0), VPX_CODEC_OK);
+
+  cfg.g_w = 128;
+  cfg.g_h = 128;
+
+  ASSERT_EQ(vpx_codec_enc_init(&enc, iface, &cfg, 0), VPX_CODEC_OK);
+
+  vpx_image_t raw;
+  ASSERT_NE(vpx_img_alloc(&raw, VPX_IMG_FMT_I420, 128, 128, 1), nullptr);
+  ASSERT_EQ(vpx_codec_encode(&enc, &raw, 0, 1, 0, VPX_DL_REALTIME),
+            VPX_CODEC_OK);
+
+  // Create a larger reference frame.
+  vpx_image_t ref_img;
+  ASSERT_NE(vpx_img_alloc(&ref_img, VPX_IMG_FMT_I420, 256, 256, 1), nullptr);
+
+  vpx_ref_frame_t ref_frame;
+  ref_frame.frame_type = VP8_LAST_FRAME;
+  ref_frame.img = ref_img;
+
+  // Setting the reference frame with incorrect size must fail.
+  EXPECT_EQ(vpx_codec_control(&enc, VP8_SET_REFERENCE, &ref_frame),
+            VPX_CODEC_INVALID_PARAM);
+
+  // Copying reference frame with incorrect size must also fail.
+  EXPECT_EQ(vpx_codec_control(&enc, VP8_COPY_REFERENCE, &ref_frame),
+            VPX_CODEC_INVALID_PARAM);
+
+  vpx_img_free(&raw);
+  vpx_img_free(&ref_img);
+  EXPECT_EQ(vpx_codec_destroy(&enc), VPX_CODEC_OK);
+}
+
 // Emulates the WebCodecs VideoEncoder interface.
 class VP8Encoder {
  public:
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index d64b870..e3a4286 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -2441,6 +2441,11 @@
     return -1;
   }
 
+  if (cm->yv12_fb[ref_fb_idx].y_width != sd->y_width ||
+      cm->yv12_fb[ref_fb_idx].y_height != sd->y_height) {
+    return -1;
+  }
+
   vp8_yv12_copy_frame(&cm->yv12_fb[ref_fb_idx], sd);
 
   return 0;
@@ -2461,6 +2466,11 @@
     return -1;
   }
 
+  if (cm->yv12_fb[ref_fb_idx].y_width != sd->y_width ||
+      cm->yv12_fb[ref_fb_idx].y_height != sd->y_height) {
+    return -1;
+  }
+
   vp8_yv12_copy_frame(sd, &cm->yv12_fb[ref_fb_idx]);
 
   return 0;
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
index e4f3c676..314f733 100644
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -1178,7 +1178,9 @@
     YV12_BUFFER_CONFIG sd;
 
     image2yuvconfig(&frame->img, &sd);
-    vp8_set_reference(ctx->cpi, frame->frame_type, &sd);
+    if (vp8_set_reference(ctx->cpi, frame->frame_type, &sd)) {
+      return VPX_CODEC_INVALID_PARAM;
+    }
     return VPX_CODEC_OK;
   } else {
     return VPX_CODEC_INVALID_PARAM;
@@ -1194,7 +1196,9 @@
     YV12_BUFFER_CONFIG sd;
 
     image2yuvconfig(&frame->img, &sd);
-    vp8_get_reference(ctx->cpi, frame->frame_type, &sd);
+    if (vp8_get_reference(ctx->cpi, frame->frame_type, &sd)) {
+      return VPX_CODEC_INVALID_PARAM;
+    }
     return VPX_CODEC_OK;
   } else {
     return VPX_CODEC_INVALID_PARAM;