Use crop dimensions for extension calculation This fixes a heap-buffer-overflow bug where extension sizes (er_y, eb_y) were calculated using storage dimensions (y_width, y_height) instead of crop dimensions (y_crop_width, y_crop_height). When size_align is large, the storage dimensions can exceed the crop dimensions significantly, leading to an inflated extension size that causes copy_and_extend_plane to write past the allocated buffer bounds. Bug: aomedia:480978101 Change-Id: I731e51f818f64183eba3377fc5b69782878b29e6
diff --git a/av1/encoder/extend.c b/av1/encoder/extend.c index c837d2f..6e77bcb 100644 --- a/av1/encoder/extend.c +++ b/av1/encoder/extend.c
@@ -115,11 +115,11 @@ // Extend src frame in buffer const int et_y = dst->border; const int el_y = dst->border; - const int er_y = - AOMMAX(src->y_width + dst->border, ALIGN_POWER_OF_TWO(src->y_width, 6)) - - src->y_crop_width; - const int eb_y = AOMMAX(src->y_height + dst->border, - ALIGN_POWER_OF_TWO(src->y_height, 6)) - + const int er_y = AOMMAX(src->y_crop_width + dst->border, + ALIGN_POWER_OF_TWO(src->y_crop_width, 6)) - + src->y_crop_width; + const int eb_y = AOMMAX(src->y_crop_height + dst->border, + ALIGN_POWER_OF_TWO(src->y_crop_height, 6)) - src->y_crop_height; const int uv_width_subsampling = src->subsampling_x; const int uv_height_subsampling = src->subsampling_y;
diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc index 47acb57..4999493 100644 --- a/test/encode_api_test.cc +++ b/test/encode_api_test.cc
@@ -1804,4 +1804,37 @@ } #endif // !CONFIG_REALTIME_ONLY +TEST(EncodeAPI, SizeAlignOverflow) { + aom_codec_iface_t *iface = aom_codec_av1_cx(); + aom_codec_enc_cfg_t cfg; + ASSERT_EQ(aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_REALTIME), + AOM_CODEC_OK); + + cfg.g_w = 16; + cfg.g_h = 16; + cfg.g_threads = 1; + cfg.g_lag_in_frames = 0; + + aom_codec_ctx_t enc; + ASSERT_EQ(aom_codec_enc_init(&enc, iface, &cfg, 0), AOM_CODEC_OK); + + // Bug aomdiea:480978101: size_align=32 causes w,h=32 while d_w,d_h=16 + // This mismatch causes buffer overflow in av1_copy_and_extend_frame() + // if the fix is not present. + aom_image_t *img = + aom_img_alloc_with_border(NULL, AOM_IMG_FMT_NV12, /*d_w=*/16, /*d_h=*/16, + /*align=*/32, + /*size_align=*/32, + /*border=*/15); + ASSERT_NE(img, nullptr); + memset(img->img_data, 128, img->sz); + + // Should not crash with heap-buffer-overflow + EXPECT_EQ(aom_codec_encode(&enc, img, /*pts=*/0, /*duration=*/1, /*flags=*/0), + AOM_CODEC_OK); + + aom_img_free(img); + ASSERT_EQ(aom_codec_destroy(&enc), AOM_CODEC_OK); +} + } // namespace