Commit 3ca3b06b42 for aom

commit 3ca3b06b42763537723a5832dfb0e5401dd4f3be
Author: Jerome Jiang <jianj@google.com>
Date:   Mon Aug 10 15:57:02 2026 -0400

    aom_img_flip: fix chroma height calculation

    Round chroma height up for odd display heights to prevent OOB read.

    Bug: 541725398
    Fixed: 541725398
    Change-Id: I6b85e6d6548b89beb40e3e116cbd34417daf9a4a

diff --git a/aom/src/aom_image.c b/aom/src/aom_image.c
index f4fdb28d8f..881429a20c 100644
--- a/aom/src/aom_image.c
+++ b/aom/src/aom_image.c
@@ -293,21 +293,31 @@ int aom_img_set_rect(aom_image_t *img, unsigned int x, unsigned int y,
 }

 void aom_img_flip(aom_image_t *img) {
+  const unsigned int chroma_height =
+      (img->d_h + img->y_chroma_shift) >> img->y_chroma_shift;
+
   /* Note: In the pointer adjustment calculations, we want the rhs to be
    * promoted to a signed type. Section 6.3.1.8 of the ISO C99 standard
    * indicates that if the first operand of the multiplication is unsigned, the
    * stride will be promoted to unsigned, causing errors when the lhs is a
    * larger type than the rhs.
    */
-  img->planes[AOM_PLANE_Y] += (signed)(img->d_h - 1) * img->stride[AOM_PLANE_Y];
+  if (img->planes[AOM_PLANE_Y]) {
+    img->planes[AOM_PLANE_Y] +=
+        (signed)(img->d_h - 1) * img->stride[AOM_PLANE_Y];
+  }
   img->stride[AOM_PLANE_Y] = -img->stride[AOM_PLANE_Y];

-  img->planes[AOM_PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1) *
-                              img->stride[AOM_PLANE_U];
+  if (img->planes[AOM_PLANE_U]) {
+    img->planes[AOM_PLANE_U] +=
+        (signed)(chroma_height - 1) * img->stride[AOM_PLANE_U];
+  }
   img->stride[AOM_PLANE_U] = -img->stride[AOM_PLANE_U];

-  img->planes[AOM_PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1) *
-                              img->stride[AOM_PLANE_V];
+  if (img->planes[AOM_PLANE_V]) {
+    img->planes[AOM_PLANE_V] +=
+        (signed)(chroma_height - 1) * img->stride[AOM_PLANE_V];
+  }
   img->stride[AOM_PLANE_V] = -img->stride[AOM_PLANE_V];
 }

diff --git a/test/aom_image_test.cc b/test/aom_image_test.cc
index 6c0059b0fd..e10c9ad3b9 100644
--- a/test/aom_image_test.cc
+++ b/test/aom_image_test.cc
@@ -141,3 +141,79 @@ TEST(AomImageTest, AomImgAllocHugeWidth) {
     aom_img_free(image);
   }
 }
+
+TEST(AomImageTest, AomImgFlipNoAlpha) {
+  aom_image_t *img = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 64, 64, 16);
+  ASSERT_NE(img, nullptr);
+  aom_img_flip(img);
+  aom_img_free(img);
+}
+
+TEST(AomImageTest, AomImgFlipOneRow) {
+  aom_image_t *img = aom_img_alloc(nullptr, AOM_IMG_FMT_I420, 16, 1, 1);
+  ASSERT_NE(img, nullptr);
+  unsigned char *const y_plane = img->planes[AOM_PLANE_Y];
+  unsigned char *const u_plane = img->planes[AOM_PLANE_U];
+  unsigned char *const v_plane = img->planes[AOM_PLANE_V];
+  const int y_stride = img->stride[AOM_PLANE_Y];
+  const int u_stride = img->stride[AOM_PLANE_U];
+  const int v_stride = img->stride[AOM_PLANE_V];
+
+  aom_img_flip(img);
+
+  EXPECT_EQ(img->planes[AOM_PLANE_Y], y_plane);
+  EXPECT_EQ(img->planes[AOM_PLANE_U], u_plane);
+  EXPECT_EQ(img->planes[AOM_PLANE_V], v_plane);
+  EXPECT_EQ(img->stride[AOM_PLANE_Y], -y_stride);
+  EXPECT_EQ(img->stride[AOM_PLANE_U], -u_stride);
+  EXPECT_EQ(img->stride[AOM_PLANE_V], -v_stride);
+
+  aom_img_flip(img);
+
+  EXPECT_EQ(img->planes[AOM_PLANE_Y], y_plane);
+  EXPECT_EQ(img->planes[AOM_PLANE_U], u_plane);
+  EXPECT_EQ(img->planes[AOM_PLANE_V], v_plane);
+  EXPECT_EQ(img->stride[AOM_PLANE_Y], y_stride);
+  EXPECT_EQ(img->stride[AOM_PLANE_U], u_stride);
+  EXPECT_EQ(img->stride[AOM_PLANE_V], v_stride);
+
+  aom_img_free(img);
+}
+
+TEST(AomImageTest, AomImgFlipOddHeight) {
+  static constexpr aom_img_fmt_t kFormats[] = {
+    AOM_IMG_FMT_YV12,   AOM_IMG_FMT_I420,   AOM_IMG_FMT_NV12,
+    AOM_IMG_FMT_I42016, AOM_IMG_FMT_YV1216,
+  };
+
+  for (const aom_img_fmt_t format : kFormats) {
+    aom_image_t *img = aom_img_alloc(nullptr, format, 16, 3, 1);
+    ASSERT_NE(img, nullptr);
+    unsigned char *const y_plane = img->planes[AOM_PLANE_Y];
+    unsigned char *const u_plane = img->planes[AOM_PLANE_U];
+    unsigned char *const v_plane = img->planes[AOM_PLANE_V];
+    const int y_stride = img->stride[AOM_PLANE_Y];
+    const int u_stride = img->stride[AOM_PLANE_U];
+    const int v_stride = img->stride[AOM_PLANE_V];
+
+    aom_img_flip(img);
+
+    EXPECT_EQ(img->planes[AOM_PLANE_Y], y_plane + 2 * y_stride);
+    EXPECT_EQ(img->planes[AOM_PLANE_U], u_plane + u_stride);
+    EXPECT_EQ(img->planes[AOM_PLANE_V], v_plane + v_stride);
+    EXPECT_EQ(img->stride[AOM_PLANE_Y], -y_stride);
+    EXPECT_EQ(img->stride[AOM_PLANE_U], -u_stride);
+    EXPECT_EQ(img->stride[AOM_PLANE_V], -v_stride);
+
+    aom_img_flip(img);
+
+    EXPECT_EQ(img->planes[AOM_PLANE_Y], y_plane);
+    EXPECT_EQ(img->planes[AOM_PLANE_U], u_plane);
+    EXPECT_EQ(img->planes[AOM_PLANE_V], v_plane);
+    EXPECT_EQ(img->stride[AOM_PLANE_Y], y_stride);
+    EXPECT_EQ(img->stride[AOM_PLANE_U], u_stride);
+    EXPECT_EQ(img->stride[AOM_PLANE_V], v_stride);
+
+    aom_img_free(img);
+  }
+}