[CFL] Clean up subsampling with function pointer

This change does not alter the encoder/decoder behavior. Extra
precautions are taken to stop an attacker from exploiting these function
pointers.

Change-Id: I4e0704f016774f2d8fbaeb2a4caec12fc6e67ec1
diff --git a/av1/common/cfl.c b/av1/common/cfl.c
index ebb4972..9593b4b 100644
--- a/av1/common/cfl.c
+++ b/av1/common/cfl.c
@@ -363,6 +363,16 @@
   }
 }
 
+typedef void (*cfl_subsample_lbd_fn)(const uint8_t *input, int input_stride,
+                                     int16_t *output_q3, int width, int height);
+
+static const cfl_subsample_lbd_fn subsample_lbd[2][2] = {
+  //  (sub_y == 0, sub_x == 0)       (sub_y == 0, sub_x == 1)
+  //  (sub_y == 1, sub_x == 0)       (sub_y == 1, sub_x == 1)
+  { cfl_luma_subsampling_444_lbd, cfl_luma_subsampling_422_lbd },
+  { cfl_luma_subsampling_440_lbd, cfl_luma_subsampling_420_lbd },
+};
+
 #if CONFIG_HIGHBITDEPTH
 static void cfl_luma_subsampling_420_hbd(const uint16_t *input,
                                          int input_stride, int16_t *output_q3,
@@ -415,71 +425,20 @@
     output_q3 += MAX_SB_SIZE;
   }
 }
+
+typedef void (*cfl_subsample_hbd_fn)(const uint16_t *input, int input_stride,
+                                     int16_t *output_q3, int width, int height);
+
+static const cfl_subsample_hbd_fn subsample_hbd[2][2] = {
+  //  (sub_y == 0, sub_x == 0)       (sub_y == 0, sub_x == 1)
+  //  (sub_y == 1, sub_x == 0)       (sub_y == 1, sub_x == 1)
+  { cfl_luma_subsampling_444_hbd, cfl_luma_subsampling_422_hbd },
+  { cfl_luma_subsampling_440_hbd, cfl_luma_subsampling_420_hbd },
+};
 #endif  // CONFIG_HIGHBITDEPTH
 
-static void cfl_luma_subsampling_420(const uint8_t *input, int input_stride,
-                                     int16_t *output_q3, int width, int height,
-                                     int use_hbd) {
-#if CONFIG_HIGHBITDEPTH
-  if (use_hbd) {
-    const uint16_t *input_16 = CONVERT_TO_SHORTPTR(input);
-    cfl_luma_subsampling_420_hbd(input_16, input_stride, output_q3, width,
-                                 height);
-    return;
-  }
-#endif  // CONFIG_HIGHBITDEPTH
-  (void)use_hbd;
-  cfl_luma_subsampling_420_lbd(input, input_stride, output_q3, width, height);
-}
-
-static void cfl_luma_subsampling_422(const uint8_t *input, int input_stride,
-                                     int16_t *output_q3, int width, int height,
-                                     int use_hbd) {
-#if CONFIG_HIGHBITDEPTH
-  if (use_hbd) {
-    const uint16_t *input_16 = CONVERT_TO_SHORTPTR(input);
-    cfl_luma_subsampling_422_hbd(input_16, input_stride, output_q3, width,
-                                 height);
-    return;
-  }
-#endif  // CONFIG_HIGHBITDEPTH
-  (void)use_hbd;
-  cfl_luma_subsampling_422_lbd(input, input_stride, output_q3, width, height);
-}
-
-static void cfl_luma_subsampling_440(const uint8_t *input, int input_stride,
-                                     int16_t *output_q3, int width, int height,
-                                     int use_hbd) {
-#if CONFIG_HIGHBITDEPTH
-  if (use_hbd) {
-    const uint16_t *input_16 = CONVERT_TO_SHORTPTR(input);
-    cfl_luma_subsampling_440_hbd(input_16, input_stride, output_q3, width,
-                                 height);
-    return;
-  }
-#endif  // CONFIG_HIGHBITDEPTH
-  (void)use_hbd;
-  cfl_luma_subsampling_440_lbd(input, input_stride, output_q3, width, height);
-}
-
-static void cfl_luma_subsampling_444(const uint8_t *input, int input_stride,
-                                     int16_t *output_q3, int width, int height,
-                                     int use_hbd) {
-#if CONFIG_HIGHBITDEPTH
-  if (use_hbd) {
-    uint16_t *input_16 = CONVERT_TO_SHORTPTR(input);
-    cfl_luma_subsampling_444_hbd(input_16, input_stride, output_q3, width,
-                                 height);
-    return;
-  }
-#endif  // CONFIG_HIGHBITDEPTH
-  (void)use_hbd;
-  cfl_luma_subsampling_444_lbd(input, input_stride, output_q3, width, height);
-}
-
-static INLINE void cfl_store(CFL_CTX *cfl, const uint8_t *input,
-                             int input_stride, int row, int col, int width,
-                             int height, int use_hbd) {
+static void cfl_store(CFL_CTX *cfl, const uint8_t *input, int input_stride,
+                      int row, int col, int width, int height, int use_hbd) {
   const int tx_off_log2 = tx_size_wide_log2[0];
   const int sub_x = cfl->subsampling_x;
   const int sub_y = cfl->subsampling_y;
@@ -510,25 +469,21 @@
   int16_t *pred_buf_q3 =
       cfl->pred_buf_q3 + (store_row * MAX_SB_SIZE + store_col);
 
-  if (sub_y == 0 && sub_x == 0) {
-    cfl_luma_subsampling_444(input, input_stride, pred_buf_q3, store_width,
-                             store_height, use_hbd);
-  } else if (sub_y == 1 && sub_x == 1) {
-    cfl_luma_subsampling_420(input, input_stride, pred_buf_q3, store_width,
-                             store_height, use_hbd);
-  } else if (sub_y == 0 && sub_x == 1) {
-    cfl_luma_subsampling_422(input, input_stride, pred_buf_q3, store_width,
-                             store_height, use_hbd);
-  } else if (sub_y == 1 && sub_x == 0) {
-    cfl_luma_subsampling_440(input, input_stride, pred_buf_q3, store_width,
-                             store_height, use_hbd);
-  } else {
-    fprintf(stderr,
-            "Only 4:4:4, 4:4:0, 4:2:2 and 4:2:0 are currently supported by "
-            "CfL, %d %d subsampling is not supported.\n",
-            sub_x, sub_y);
-    abort();
+#if CONFIG_HIGHBITDEPTH
+  if (use_hbd) {
+    const uint16_t *input_16 = CONVERT_TO_SHORTPTR(input);
+    // AND sub_x and sub_y with 1 to ensures that an attacker won't be able to
+    // index the function pointer array out of bounds.
+    subsample_hbd[sub_y & 1][sub_x & 1](input_16, input_stride, pred_buf_q3,
+                                        store_width, store_height);
+    return;
   }
+#endif  // CONFIG_HIGHBITDEPTH
+  (void)use_hbd;
+  // AND sub_x and sub_y with 1 to ensures that an attacker won't be able to
+  // index the function pointer array out of bounds.
+  subsample_lbd[sub_y & 1][sub_x & 1](input, input_stride, pred_buf_q3,
+                                      store_width, store_height);
 }
 
 // Adjust the row and column of blocks smaller than 8X8, as chroma-referenced