Commit 7343efd164 for aom
commit 7343efd164afc3c0f9f2a212052d77a3d7ea1a49
Author: Jerome Jiang <jianj@google.com>
Date: Fri Feb 20 15:50:04 2026 -0500
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 c837d2f199..6e77bcbfd1 100644
--- a/av1/encoder/extend.c
+++ b/av1/encoder/extend.c
@@ -115,11 +115,11 @@ void av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
// 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 47acb57181..4999493b98 100644
--- a/test/encode_api_test.cc
+++ b/test/encode_api_test.cc
@@ -1804,4 +1804,37 @@ TEST_F(GetGopInfoTest, GetGopInfo) {
}
#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