CVE-2021-37686: Loop with Unreachable Exit Condition ('Infinite Loop') (CWE-835)
value: TensorFlow is an end-to-end open source platform for machine learning. In affected versions the strided slice implementation in TFLite has a logic bug which can allow an attacker to trigger an infinite loop. This arises from newly introduced support for [ellipsis in axis definition](https://github.com/tensorflow/tensorflow/blob/149562d49faa709ea80df1d99fc41d005b81082a/tensorflow/lite/kernels/strided_slice.cc#L103-L122). An attacker can craft a model such that `ellipsis_end_idx` is smaller than `i` (e.g., always negative). In this case, the inner loop does not increase `i` and the `continue` statement causes execution to skip over the preincrement at the end of the outer loop. We have patched the issue in GitHub commit dfa22b348b70bb89d6d6ec0ff53973bacb4f4695. TensorFlow 2.6.0 is the only affected version.
CWE description: The product contains an iteration or loop with an exit condition that cannot be reached, i.e., an infinite loop.
CVSS v3 base score: 5.5
Published: 2021-08-12T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C
Files changed: tensorflow/lite/kernels/internal/averagepool_quantized_test.cc, tensorflow/lite/kernels/internal/optimized/integer_ops/pooling.h, tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h, tensorflow/lite/kernels/internal/optimized/optimized_ops.h, tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h, tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h, tensorflow/lite/kernels/internal/reference/pooling.h, tensorflow/lite/kernels/pooling.cc
Commit date: 2021-07-16 11:15:34 -0700
Commit message: Prevent a division by 0 in average ops.

PiperOrigin-RevId: 385184660
Change-Id: I7affd4554f9b336fca29ac68f633232c094d0bd3

Diff: diff --git a/tensorflow/lite/kernels/internal/averagepool_quantized_test.cc b/tensorflow/lite/kernels/internal/averagepool_quantized_test.cc
index cbc863645b74b..fea343ae6b882 100644
--- a/tensorflow/lite/kernels/internal/averagepool_quantized_test.cc
+++ b/tensorflow/lite/kernels/internal/averagepool_quantized_test.cc
@@ -38,16 +38,18 @@ void RunOneAveragePoolTest(const PoolParams& params,
                            const RuntimeShape& output_shape) {
   const int buffer_size = output_shape.FlatSize();
   std::vector<int8> optimized_averagePool_output(buffer_size);
   std::vector<int8> reference_averagePool_output(buffer_size);
 
-  reference_integer_ops::AveragePool(params, input_shape, input_data,
-                                     output_shape,
-                                     reference_averagePool_output.data());
-  optimized_integer_ops::AveragePool(params, input_shape, input_data,
-                                     output_shape,
-                                     optimized_averagePool_output.data());
+  bool reference_success = reference_integer_ops::AveragePool(
+      params, input_shape, input_data, output_shape,
+      reference_averagePool_output.data());
+  bool optimized_success = optimized_integer_ops::AveragePool(
+      params, input_shape, input_data, output_shape,
+      optimized_averagePool_output.data());
+  EXPECT_TRUE(reference_success);
+  EXPECT_TRUE(optimized_success);
 
   for (int i = 0; i < buffer_size; i++) {
     EXPECT_TRUE(reference_averagePool_output[i] ==
                 optimized_averagePool_output[i]);
   }
diff --git a/tensorflow/lite/kernels/internal/optimized/integer_ops/pooling.h b/tensorflow/lite/kernels/internal/optimized/integer_ops/pooling.h
index 17495135038c6..0a6d63d3fabea 100644
--- a/tensorflow/lite/kernels/internal/optimized/integer_ops/pooling.h
+++ b/tensorflow/lite/kernels/internal/optimized/integer_ops/pooling.h
@@ -142,11 +142,11 @@ inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
       }
     }
   }
 }
 
-inline void AveragePool(const PoolParams& params,
+inline bool AveragePool(const PoolParams& params,
                         const RuntimeShape& input_shape, const int8* input_data,
                         const RuntimeShape& output_shape, int8* output_data) {
   ruy::profiler::ScopeLabel label("AveragePool/8bitWith32bitAccumulator");
 
   // Here, and in other pooling ops, in order to maintain locality of reference,
@@ -190,10 +190,11 @@ inline void AveragePool(const PoolParams& params,
           const int filter_y_start = std::max(0, -in_y_origin);
           const int filter_y_end =
               std::min(params.filter_height, input_height - in_y_origin);
           const int filter_count =
               (filter_x_end - filter_x_start) * (filter_y_end - filter_y_start);
+          if (filter_count == 0) return false;
           memset(acc, 0, tranche_depth * sizeof(acc[0]));
           const int8* input_ptr =
               input_data + depth_base +
               depth * (in_x_origin +
                        input_width * (in_y_origin + input_height * batch));
@@ -265,10 +266,11 @@ inline void AveragePool(const PoolParams& params,
           }
         }
       }
     }
   }
+  return true;
 }
 
 }  // namespace optimized_integer_ops
 }  // namespace tflite
 
diff --git a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h
index 44a553c527ab2..76b8d4c55a5e9 100644
--- a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h
+++ b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h
@@ -3759,11 +3759,11 @@ inline void BroadcastMul(const uint8* input1_data, const Dims<4>& input1_dims,
                input2_dims, input2_offset, output_offset, output_multiplier,
                output_shift, output_activation_min, output_activation_max,
                output_data, output_dims);
 }
 
-inline void AveragePool(const float* input_data, const Dims<4>& input_dims,
+inline bool AveragePool(const float* input_data, const Dims<4>& input_dims,
                         int stride_width, int stride_height, int pad_width,
                         int pad_height, int kwidth, int kheight,
                         float output_activation_min,
                         float output_activation_max, float* output_data,
                         const Dims<4>& output_dims) {
@@ -3774,39 +3774,41 @@ inline void AveragePool(const float* input_data, const Dims<4>& input_dims,
   params.filter_width = kwidth;
   params.padding_values.height = pad_height;
   params.padding_values.width = pad_width;
   params.float_activation_min = output_activation_min;
   params.float_activation_max = output_activation_max;
-  AveragePool(params, DimsToShape(input_dims), input_data,
-              DimsToShape(output_dims), output_data);
+  return AveragePool(params, DimsToShape(input_dims), input_data,
+                     DimsToShape(output_dims), output_data);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const float* input_data, const Dims<4>& input_dims,
+bool AveragePool(const float* input_data, const Dims<4>& input_dims,
                  int stride_width, int stride_height, int pad_width,
                  int pad_height, int kwidth, int kheight, float* output_data,
                  const Dims<4>& output_dims) {
   float output_activation_min, output_activation_max;
   GetActivationMinMax(Ac, &output_activation_min, &output_activation_max);
 
-  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
-              pad_height, kwidth, kheight, output_activation_min,
-              output_activation_max, output_data, output_dims);
+  return AveragePool(input_data, input_dims, stride_width, stride_height,
+                     pad_width, pad_height, kwidth, kheight,
+                     output_activation_min, output_activation_max, output_data,
+                     output_dims);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
+bool AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
                  int pad_width, int pad_height, int filter_width,
                  int filter_height, float* output_data,
                  const Dims<4>& output_dims) {
-  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
-                  filter_width, filter_height, output_data, output_dims);
+  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
+                         pad_height, filter_width, filter_height, output_data,
+                         output_dims);
 }
 
-inline void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
+inline bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
                         int stride_width, int stride_height, int pad_width,
                         int pad_height, int filter_width, int filter_height,
                         int32 output_activation_min,
                         int32 output_activation_max, uint8* output_data,
                         const Dims<4>& output_dims) {
@@ -3817,17 +3819,17 @@ inline void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
   params.filter_width = filter_width;
   params.padding_values.height = pad_height;
   params.padding_values.width = pad_width;
   params.quantized_activation_min = output_activation_min;
   params.quantized_activation_max = output_activation_max;
-  AveragePool(params, DimsToShape(input_dims), input_data,
-              DimsToShape(output_dims), output_data);
+  return AveragePool(params, DimsToShape(input_dims), input_data,
+                     DimsToShape(output_dims), output_data);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
+bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
                  int stride_width, int stride_height, int pad_width,
                  int pad_height, int filter_width, int filter_height,
                  int32 output_activation_min, int32 output_activation_max,
                  uint8* output_data, const Dims<4>& output_dims) {
   static_assert(Ac == FusedActivationFunctionType::kNone ||
@@ -3837,25 +3839,27 @@ void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
                 "");
   if (Ac == FusedActivationFunctionType::kNone) {
     TFLITE_DCHECK_EQ(output_activation_min, 0);
     TFLITE_DCHECK_EQ(output_activation_max, 255);
   }
-  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
-              pad_height, filter_width, filter_height, output_activation_min,
-              output_activation_max, output_data, output_dims);
+  return AveragePool(input_data, input_dims, stride_width, stride_height,
+                     pad_width, pad_height, filter_width, filter_height,
+                     output_activation_min, output_activation_max, output_data,
+                     output_dims);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
+bool AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
                  int pad_width, int pad_height, int filter_width,
                  int filter_height, int32 output_activation_min,
                  int32 output_activation_max, uint8* output_data,
                  const Dims<4>& output_dims) {
-  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
-                  filter_width, filter_height, output_activation_min,
-                  output_activation_max, output_data, output_dims);
+  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
+                         pad_height, filter_width, filter_height,
+                         output_activation_min, output_activation_max,
+                         output_data, output_dims);
 }
 
 inline void MaxPool(const float* input_data, const Dims<4>& input_dims,
                     int stride_width, int stride_height, int pad_width,
                     int pad_height, int kwidth, int kheight,
diff --git a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h
index a5abb056c46e6..241405a6bbae1 100644
--- a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h
+++ b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h
@@ -3170,11 +3170,11 @@ inline void LstmCell(
 
 inline int NodeOffset(int b, int h, int w, int height, int width) {
   return (b * height + h) * width + w;
 }
 
-inline void AveragePool(const PoolParams& params,
+inline bool AveragePool(const PoolParams& params,
                         const RuntimeShape& input_shape,
                         const float* input_data,
                         const RuntimeShape& output_shape, float* output_data) {
   ruy::profiler::ScopeLabel label("AveragePool");
   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
@@ -3185,10 +3185,13 @@ inline void AveragePool(const PoolParams& params,
   const int output_height = output_shape.Dims(1);
   const int output_width = output_shape.Dims(2);
   const int stride_height = params.stride_height;
   const int stride_width = params.stride_width;
 
+  if (stride_height == 0) return false;
+  if (stride_width == 0) return false;
+
   // TODO(benoitjacob) make this a proper reference impl without Eigen!
   const auto in_mat = MapAsMatrixWithLastDimAsRows(input_data, input_shape);
   auto out_mat = MapAsMatrixWithLastDimAsRows(output_data, output_shape);
   // TODO(benoitjacob) get rid of the dynamic memory allocation here!
   Eigen::VectorXf out_count(out_mat.cols());
@@ -3230,13 +3233,15 @@ inline void AveragePool(const PoolParams& params,
   for (int i = 0; i < flat_size; ++i) {
     output_data[i] = ActivationFunctionWithMinMax(output_data[i],
                                                   params.float_activation_min,
                                                   params.float_activation_max);
   }
+
+  return true;
 }
 
-inline void AveragePool(const PoolParams& params,
+inline bool AveragePool(const PoolParams& params,
                         const RuntimeShape& input_shape,
                         const uint8* input_data,
                         const RuntimeShape& output_shape, uint8* output_data) {
   ruy::profiler::ScopeLabel label("AveragePool/8bit");
 
@@ -3281,10 +3286,11 @@ inline void AveragePool(const PoolParams& params,
           const int filter_y_start = std::max(0, -in_y_origin);
           const int filter_y_end =
               std::min(params.filter_height, input_height - in_y_origin);
           const int filter_count =
               (filter_x_end - filter_x_start) * (filter_y_end - filter_y_start);
+          if (filter_count == 0) return false;
           memset(acc, 0, tranche_depth * sizeof(acc[0]));
           const uint8* input_ptr =
               input_data + depth_base +
               depth * (in_x_origin +
                        input_width * (in_y_origin + input_height * batch));
@@ -3367,10 +3373,11 @@ inline void AveragePool(const PoolParams& params,
           }
         }
       }
     }
   }
+  return true;
 }
 
 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
                     const float* input_data, const RuntimeShape& output_shape,
                     float* output_data) {
diff --git a/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h b/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h
index 17944bc47dd5d..2cb4dada8a66e 100644
--- a/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h
+++ b/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h
@@ -19,11 +19,11 @@ limitations under the License.
 #include "tensorflow/lite/kernels/internal/common.h"
 
 namespace tflite {
 namespace reference_integer_ops {
 
-inline void AveragePool(const PoolParams& params,
+inline bool AveragePool(const PoolParams& params,
                         const RuntimeShape& input_shape,
                         const int8_t* input_data,
                         const RuntimeShape& output_shape, int8_t* output_data) {
   TFLITE_DCHECK_LE(params.quantized_activation_min,
                    params.quantized_activation_max);
@@ -64,10 +64,11 @@ inline void AveragePool(const PoolParams& params,
               acc +=
                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
               filter_count++;
             }
           }
+          if (filter_count == 0) return false;
           // Round to the closest integer value.
           acc = acc > 0 ? (acc + filter_count / 2) / filter_count
                         : (acc - filter_count / 2) / filter_count;
           acc = std::max(acc, params.quantized_activation_min);
           acc = std::min(acc, params.quantized_activation_max);
@@ -75,10 +76,11 @@ inline void AveragePool(const PoolParams& params,
               static_cast<int8_t>(acc);
         }
       }
     }
   }
+  return true;
 }
 
 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
                     const int8_t* input_data, const RuntimeShape& output_shape,
                     int8_t* output_data) {
@@ -134,11 +136,11 @@ inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
       }
     }
   }
 }
 
-inline void AveragePool(const PoolParams& params,
+inline bool AveragePool(const PoolParams& params,
                         const RuntimeShape& input_shape,
                         const int16_t* input_data,
                         const RuntimeShape& output_shape,
                         int16_t* output_data) {
   TFLITE_DCHECK_LE(params.quantized_activation_min,
@@ -180,10 +182,11 @@ inline void AveragePool(const PoolParams& params,
               acc +=
                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
               filter_count++;
             }
           }
+          if (filter_count == 0) return false;
           // Round to the closest integer value.
           acc = acc > 0 ? (acc + filter_count / 2) / filter_count
                         : (acc - filter_count / 2) / filter_count;
           acc = std::max(acc, params.quantized_activation_min);
           acc = std::min(acc, params.quantized_activation_max);
@@ -191,10 +194,11 @@ inline void AveragePool(const PoolParams& params,
               static_cast<int16_t>(acc);
         }
       }
     }
   }
+  return true;
 }
 
 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
                     const int16_t* input_data, const RuntimeShape& output_shape,
                     int16_t* output_data) {
diff --git a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h
index 2d7056fcd855e..0b65b1f49cf38 100644
--- a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h
+++ b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h
@@ -1485,11 +1485,11 @@ void Sub(const T* input1_data, const Dims<4>& input1_dims, const T* input2_data,
   Sub(op_params, DimsToShape(input1_dims), input1_data,
       DimsToShape(input2_dims), input2_data, DimsToShape(output_dims),
       output_data);
 }
 
-inline void AveragePool(const float* input_data, const Dims<4>& input_dims,
+inline bool AveragePool(const float* input_data, const Dims<4>& input_dims,
                         int stride_width, int stride_height, int pad_width,
                         int pad_height, int kwidth, int kheight,
                         float output_activation_min,
                         float output_activation_max, float* output_data,
                         const Dims<4>& output_dims) {
@@ -1500,12 +1500,12 @@ inline void AveragePool(const float* input_data, const Dims<4>& input_dims,
   params.filter_width = kwidth;
   params.padding_values.height = pad_height;
   params.padding_values.width = pad_width;
   params.float_activation_min = output_activation_min;
   params.float_activation_max = output_activation_max;
-  AveragePool(params, DimsToShape(input_dims), input_data,
-              DimsToShape(output_dims), output_data);
+  return AveragePool(params, DimsToShape(input_dims), input_data,
+                     DimsToShape(output_dims), output_data);
 }
 
 // Transitional version that will be moved shortly to legacy_reference_ops, as
 // part of RuntimeShape revisions.
 inline void BroadcastMul4DSlow(const uint8* input1_data,
@@ -1560,33 +1560,35 @@ inline void BroadcastMul(const uint8* input1_data, const Dims<4>& input1_dims,
                output_data, output_dims);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const float* input_data, const Dims<4>& input_dims,
+bool AveragePool(const float* input_data, const Dims<4>& input_dims,
                  int stride_width, int stride_height, int pad_width,
                  int pad_height, int kwidth, int kheight, float* output_data,
                  const Dims<4>& output_dims) {
   float output_activation_min, output_activation_max;
   GetActivationMinMax(Ac, &output_activation_min, &output_activation_max);
 
-  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
-              pad_height, kwidth, kheight, output_activation_min,
-              output_activation_max, output_data, output_dims);
+  return AveragePool(input_data, input_dims, stride_width, stride_height,
+                     pad_width, pad_height, kwidth, kheight,
+                     output_activation_min, output_activation_max, output_data,
+                     output_dims);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
+bool AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
                  int pad_width, int pad_height, int filter_width,
                  int filter_height, float* output_data,
                  const Dims<4>& output_dims) {
-  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
-                  filter_width, filter_height, output_data, output_dims);
+  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
+                         pad_height, filter_width, filter_height, output_data,
+                         output_dims);
 }
 
-inline void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
+inline bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
                         int stride_width, int stride_height, int pad_width,
                         int pad_height, int filter_width, int filter_height,
                         int32 output_activation_min,
                         int32 output_activation_max, uint8* output_data,
                         const Dims<4>& output_dims) {
@@ -1597,17 +1599,17 @@ inline void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
   params.filter_width = filter_width;
   params.padding_values.height = pad_height;
   params.padding_values.width = pad_width;
   params.quantized_activation_min = output_activation_min;
   params.quantized_activation_max = output_activation_max;
-  AveragePool(params, DimsToShape(input_dims), input_data,
-              DimsToShape(output_dims), output_data);
+  return AveragePool(params, DimsToShape(input_dims), input_data,
+                     DimsToShape(output_dims), output_data);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
+bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
                  int stride_width, int stride_height, int pad_width,
                  int pad_height, int filter_width, int filter_height,
                  int32 output_activation_min, int32 output_activation_max,
                  uint8* output_data, const Dims<4>& output_dims) {
   static_assert(Ac == FusedActivationFunctionType::kNone ||
@@ -1617,25 +1619,27 @@ void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
                 "");
   if (Ac == FusedActivationFunctionType::kNone) {
     TFLITE_DCHECK_EQ(output_activation_min, 0);
     TFLITE_DCHECK_EQ(output_activation_max, 255);
   }
-  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
-              pad_height, filter_width, filter_height, output_activation_min,
-              output_activation_max, output_data, output_dims);
+  return AveragePool(input_data, input_dims, stride_width, stride_height,
+                     pad_width, pad_height, filter_width, filter_height,
+                     output_activation_min, output_activation_max, output_data,
+                     output_dims);
 }
 
 // legacy, for compatibility with old checked-in code
 template <FusedActivationFunctionType Ac>
-void AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
+bool AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
                  int pad_width, int pad_height, int filter_width,
                  int filter_height, int32 output_activation_min,
                  int32 output_activation_max, uint8* output_data,
                  const Dims<4>& output_dims) {
-  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
-                  filter_width, filter_height, output_activation_min,
-                  output_activation_max, output_data, output_dims);
+  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
+                         pad_height, filter_width, filter_height,
+                         output_activation_min, output_activation_max,
+                         output_data, output_dims);
 }
 
 inline void MaxPool(const float* input_data, const Dims<4>& input_dims,
                     int stride_width, int stride_height, int pad_width,
                     int pad_height, int kwidth, int kheight,
diff --git a/tensorflow/lite/kernels/internal/reference/pooling.h b/tensorflow/lite/kernels/internal/reference/pooling.h
index 0872f5210c8ed..ee30b8404464b 100644
--- a/tensorflow/lite/kernels/internal/reference/pooling.h
+++ b/tensorflow/lite/kernels/internal/reference/pooling.h
@@ -21,11 +21,11 @@ limitations under the License.
 #include "tensorflow/lite/kernels/internal/types.h"
 
 namespace tflite {
 namespace reference_ops {
 
-inline void AveragePool(const PoolParams& params,
+inline bool AveragePool(const PoolParams& params,
                         const RuntimeShape& input_shape,
                         const float* input_data,
                         const RuntimeShape& output_shape, float* output_data) {
   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
@@ -64,21 +64,23 @@ inline void AveragePool(const PoolParams& params,
               total +=
                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
               filter_count++;
             }
           }
+          if (filter_count == 0) return false;
           const float average = total / filter_count;
           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
               ActivationFunctionWithMinMax(average, params.float_activation_min,
                                            params.float_activation_max);
         }
       }
     }
   }
+  return true;
 }
 
-inline void AveragePool(const PoolParams& params,
+inline bool AveragePool(const PoolParams& params,
                         const RuntimeShape& input_shape,
                         const uint8_t* input_data,
                         const RuntimeShape& output_shape,
                         uint8_t* output_data) {
   TFLITE_DCHECK_LE(params.quantized_activation_min,
@@ -120,19 +122,21 @@ inline void AveragePool(const PoolParams& params,
               acc +=
                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
               filter_count++;
             }
           }
+          if (filter_count == 0) return false;
           acc = (acc + filter_count / 2) / filter_count;
           acc = std::max(acc, params.quantized_activation_min);
           acc = std::min(acc, params.quantized_activation_max);
           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
               static_cast<uint8_t>(acc);
         }
       }
     }
   }
+  return true;
 }
 
 inline void L2Pool(const PoolParams& params, const RuntimeShape& input_shape,
                    const float* input_data, const RuntimeShape& output_shape,
                    float* output_data) {
diff --git a/tensorflow/lite/kernels/pooling.cc b/tensorflow/lite/kernels/pooling.cc
index 474bd3825f4ff..d54bd89b22151 100644
--- a/tensorflow/lite/kernels/pooling.cc
+++ b/tensorflow/lite/kernels/pooling.cc
@@ -115,121 +115,130 @@ TfLiteStatus GenericPrepare(TfLiteContext* context, TfLiteNode* node) {
   output_size->data[3] = channels_out;
   return context->ResizeTensor(context, output, output_size);
 }
 
 template <KernelType kernel_type>
-void AverageEvalFloat(TfLiteContext* context, TfLiteNode* node,
-                      TfLitePoolParams* params, OpData* data,
-                      const TfLiteTensor* input, TfLiteTensor* output) {
+TfLiteStatus AverageEvalFloat(TfLiteContext* context, TfLiteNode* node,
+                              TfLitePoolParams* params, OpData* data,
+                              const TfLiteTensor* input, TfLiteTensor* output) {
   float activation_min, activation_max;
   CalculateActivationRange(params->activation, &activation_min,
                            &activation_max);
-#define TF_LITE_AVERAGE_POOL(type)                                       \
-  tflite::PoolParams op_params;                                          \
-  op_params.stride_height = params->stride_height;                       \
-  op_params.stride_width = params->stride_width;                         \
-  op_params.filter_height = params->filter_height;                       \
-  op_params.filter_width = params->filter_width;                         \
-  op_params.padding_values.height = data->padding.height;                \
-  op_params.padding_values.width = data->padding.width;                  \
-  op_params.float_activation_min = activation_min;                       \
-  op_params.float_activation_max = activation_max;                       \
-  type::AveragePool(op_params, GetTensorShape(input),                    \
-                    GetTensorData<float>(input), GetTensorShape(output), \
-                    GetTensorData<float>(output))
+#define TF_LITE_AVERAGE_POOL(type)                                            \
+  tflite::PoolParams op_params;                                               \
+  op_params.stride_height = params->stride_height;                            \
+  op_params.stride_width = params->stride_width;                              \
+  op_params.filter_height = params->filter_height;                            \
+  op_params.filter_width = params->filter_width;                              \
+  op_params.padding_values.height = data->padding.height;                     \
+  op_params.padding_values.width = data->padding.width;                       \
+  op_params.float_activation_min = activation_min;                            \
+  op_params.float_activation_max = activation_max;                            \
+  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
+                                            GetTensorData<float>(input),      \
+                                            GetTensorShape(output),           \
+                                            GetTensorData<float>(output)))
   if (kernel_type == kReference) {
     TF_LITE_AVERAGE_POOL(reference_ops);
   } else {
     TF_LITE_AVERAGE_POOL(optimized_ops);
   }
 #undef TF_LITE_AVERAGE_POOL
+  return kTfLiteOk;
 }
 
 template <KernelType kernel_type>
-void AverageEvalQuantizedUint8(TfLiteContext* context, TfLiteNode* node,
-                               TfLitePoolParams* params, OpData* data,
-                               const TfLiteTensor* input,
-                               TfLiteTensor* output) {
+TfLiteStatus AverageEvalQuantizedUint8(TfLiteContext* context, TfLiteNode* node,
+                                       TfLitePoolParams* params, OpData* data,
+                                       const TfLiteTensor* input,
+                                       TfLiteTensor* output) {
   int32_t activation_min;
   int32_t activation_max;
   (void)CalculateActivationRangeQuantized(context, params->activation, output,
                                           &activation_min, &activation_max);
-#define TF_LITE_AVERAGE_POOL(type)                                         \
-  tflite::PoolParams op_params;                                            \
-  op_params.stride_height = params->stride_height;                         \
-  op_params.stride_width = params->stride_width;                           \
-  op_params.filter_height = params->filter_height;                         \
-  op_params.filter_width = params->filter_width;                           \
-  op_params.padding_values.height = data->padding.height;                  \
-  op_params.padding_values.width = data->padding.width;                    \
-  op_params.quantized_activation_min = activation_min;                     \
-  op_params.quantized_activation_max = activation_max;                     \
-  type::AveragePool(op_params, GetTensorShape(input),                      \
-                    GetTensorData<uint8_t>(input), GetTensorShape(output), \
-                    GetTensorData<uint8_t>(output))
+#define TF_LITE_AVERAGE_POOL(type)                                            \
+  tflite::PoolParams op_params;                                               \
+  op_params.stride_height = params->stride_height;                            \
+  op_params.stride_width = params->stride_width;                              \
+  op_params.filter_height = params->filter_height;                            \
+  op_params.filter_width = params->filter_width;                              \
+  op_params.padding_values.height = data->padding.height;                     \
+  op_params.padding_values.width = data->padding.width;                       \
+  op_params.quantized_activation_min = activation_min;                        \
+  op_params.quantized_activation_max = activation_max;                        \
+  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
+                                            GetTensorData<uint8_t>(input),    \
+                                            GetTensorShape(output),           \
+                                            GetTensorData<uint8_t>(output)))
   if (kernel_type == kReference) {
     TF_LITE_AVERAGE_POOL(reference_ops);
   } else {
     TF_LITE_AVERAGE_POOL(optimized_ops);
   }
 #undef TF_LITE_AVERAGE_POOL
+  return kTfLiteOk;
 }
 
 template <KernelType kernel_type>
-void AverageEvalQuantizedInt8(TfLiteContext* context, TfLiteNode* node,
-                              TfLitePoolParams* params, OpData* data,
-                              const TfLiteTensor* input, TfLiteTensor* output) {
+TfLiteStatus AverageEvalQuantizedInt8(TfLiteContext* context, TfLiteNode* node,
+                                      TfLitePoolParams* params, OpData* data,
+                                      const TfLiteTensor* input,
+                                      TfLiteTensor* output) {
   int32_t activation_min;
   int32_t activation_max;
 
   (void)CalculateActivationRangeQuantized(context, params->activation, output,
                                           &activation_min, &activation_max);
-#define TF_LITE_AVERAGE_POOL(type)                                        \
-  tflite::PoolParams op_params;                                           \
-  op_params.stride_height = params->stride_height;                        \
-  op_params.stride_width = params->stride_width;                          \
-  op_params.filter_height = params->filter_height;                        \
-  op_params.filter_width = params->filter_width;                          \
-  op_params.padding_values.height = data->padding.height;                 \
-  op_params.padding_values.width = data->padding.width;                   \
-  op_params.quantized_activation_min = activation_min;                    \
-  op_params.quantized_activation_max = activation_max;                    \
-  type::AveragePool(op_params, GetTensorShape(input),                     \
-                    GetTensorData<int8_t>(input), GetTensorShape(output), \
-                    GetTensorData<int8_t>(output))
+#define TF_LITE_AVERAGE_POOL(type)                                            \
+  tflite::PoolParams op_params;                                               \
+  op_params.stride_height = params->stride_height;                            \
+  op_params.stride_width = params->stride_width;                              \
+  op_params.filter_height = params->filter_height;                            \
+  op_params.filter_width = params->filter_width;                              \
+  op_params.padding_values.height = data->padding.height;                     \
+  op_params.padding_values.width = data->padding.width;                       \
+  op_params.quantized_activation_min = activation_min;                        \
+  op_params.quantized_activation_max = activation_max;                        \
+  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
+                                            GetTensorData<int8_t>(input),     \
+                                            GetTensorShape(output),           \
+                                            GetTensorData<int8_t>(output)))
   if (kernel_type == kReference) {
     TF_LITE_AVERAGE_POOL(reference_integer_ops);
   } else {
     TF_LITE_AVERAGE_POOL(optimized_integer_ops);
   }
 #undef TF_LITE_AVERAGE_POOL
+  return kTfLiteOk;
 }
 
 template <KernelType kernel_type>
-void AverageEvalQuantizedInt16(TfLiteContext* context, TfLiteNode* node,
-                               TfLitePoolParams* params, OpData* data,
-                               const TfLiteTensor* input,
-                               TfLiteTensor* output) {
+TfLiteStatus AverageEvalQuantizedInt16(TfLiteContext* context, TfLiteNode* node,
+                                       TfLitePoolParams* params, OpData* data,
+                                       const TfLiteTensor* input,
+                                       TfLiteTensor* output) {
   int32_t activation_min;
   int32_t activation_max;
   CalculateActivationRangeQuantized(context, params->activation, output,
                                     &activation_min, &activation_max);
-#define TF_LITE_AVERAGE_POOL(type)                                         \
-  tflite::PoolParams op_params;                                            \
-  op_params.stride_height = params->stride_height;                         \
-  op_params.stride_width = params->stride_width;                           \
-  op_params.filter_height = params->filter_height;                         \
-  op_params.filter_width = params->filter_width;                           \
-  op_params.padding_values.height = data->padding.height;                  \
-  op_params.padding_values.width = data->padding.width;                    \
-  op_params.quantized_activation_min = activation_min;                     \
-  op_params.quantized_activation_max = activation_max;                     \
-  type::AveragePool(op_params, GetTensorShape(input),                      \
-                    GetTensorData<int16_t>(input), GetTensorShape(output), \
-                    GetTensorData<int16_t>(output))
+#define TF_LITE_AVERAGE_POOL(type)                                            \
+  tflite::PoolParams op_params;                                               \
+  op_params.stride_height = params->stride_height;                            \
+  op_params.stride_width = params->stride_width;                              \
+  op_params.filter_height = params->filter_height;                            \
+  op_params.filter_width = params->filter_width;                              \
+  op_params.padding_values.height = data->padding.height;                     \
+  op_params.padding_values.width = data->padding.width;                       \
+  op_params.quantized_activation_min = activation_min;                        \
+  op_params.quantized_activation_max = activation_max;                        \
+  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
+                                            GetTensorData<int16_t>(input),    \
+                                            GetTensorShape(output),           \
+                                            GetTensorData<int16_t>(output)))
   TF_LITE_AVERAGE_POOL(reference_integer_ops);
 #undef TF_LITE_AVERAGE_POOL
+  return kTfLiteOk;
 }
 
 template <KernelType kernel_type>
 void MaxEvalFloat(TfLiteContext* context, TfLiteNode* node,
                   TfLitePoolParams* params, OpData* data,
@@ -378,24 +387,21 @@ TfLiteStatus AverageEval(TfLiteContext* context, TfLiteNode* node) {
   TF_LITE_ENSURE_OK(context, GetOutputSafe(context, node, 0, &output));
   const TfLiteTensor* input;
   TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, 0, &input));
   switch (input->type) {  // Already know in/out types are same.
     case kTfLiteFloat32:
-      AverageEvalFloat<kernel_type>(context, node, params, data, input, output);
-      break;
+      return AverageEvalFloat<kernel_type>(context, node, params, data, input,
+                                           output);
     case kTfLiteUInt8:
-      AverageEvalQuantizedUint8<kernel_type>(context, node, params, data, input,
-                                             output);
-      break;
+      return AverageEvalQuantizedUint8<kernel_type>(context, node, params, data,
+                                                    input, output);
     case kTfLiteInt8:
-      AverageEvalQuantizedInt8<kernel_type>(context, node, params, data, input,
-                                            output);
-      break;
+      return AverageEvalQuantizedInt8<kernel_type>(context, node, params, data,
+                                                   input, output);
     case kTfLiteInt16:
-      AverageEvalQuantizedInt16<kernel_type>(context, node, params, data, input,
-                                             output);
-      break;
+      return AverageEvalQuantizedInt16<kernel_type>(context, node, params, data,
+                                                    input, output);
     default:
       TF_LITE_KERNEL_LOG(context, "Type %s not currently supported.",
                          TfLiteTypeGetName(input->type));
       return kTfLiteError;
   }

Vulnerable code:   reference_integer_ops::AveragePool(params, input_shape, input_data,
                                     output_shape,
                                     reference_averagePool_output.data());
  optimized_integer_ops::AveragePool(params, input_shape, input_data,
                                     output_shape,
                                     optimized_averagePool_output.data());
inline void AveragePool(const PoolParams& params,
inline void AveragePool(const float* input_data, const Dims<4>& input_dims,
  AveragePool(params, DimsToShape(input_dims), input_data,
              DimsToShape(output_dims), output_data);
void AveragePool(const float* input_data, const Dims<4>& input_dims,
  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
              pad_height, kwidth, kheight, output_activation_min,
              output_activation_max, output_data, output_dims);
void AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
                  filter_width, filter_height, output_data, output_dims);
inline void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  AveragePool(params, DimsToShape(input_dims), input_data,
              DimsToShape(output_dims), output_data);
void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
              pad_height, filter_width, filter_height, output_activation_min,
              output_activation_max, output_data, output_dims);
void AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
                  filter_width, filter_height, output_activation_min,
                  output_activation_max, output_data, output_dims);
inline void AveragePool(const PoolParams& params,
inline void AveragePool(const PoolParams& params,
inline void AveragePool(const PoolParams& params,
inline void AveragePool(const PoolParams& params,
inline void AveragePool(const float* input_data, const Dims<4>& input_dims,
  AveragePool(params, DimsToShape(input_dims), input_data,
              DimsToShape(output_dims), output_data);
void AveragePool(const float* input_data, const Dims<4>& input_dims,
  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
              pad_height, kwidth, kheight, output_activation_min,
              output_activation_max, output_data, output_dims);
void AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
                  filter_width, filter_height, output_data, output_dims);
inline void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  AveragePool(params, DimsToShape(input_dims), input_data,
              DimsToShape(output_dims), output_data);
void AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  AveragePool(input_data, input_dims, stride_width, stride_height, pad_width,
              pad_height, filter_width, filter_height, output_activation_min,
              output_activation_max, output_data, output_dims);
void AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
  AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width, pad_height,
                  filter_width, filter_height, output_activation_min,
                  output_activation_max, output_data, output_dims);
inline void AveragePool(const PoolParams& params,
inline void AveragePool(const PoolParams& params,
void AverageEvalFloat(TfLiteContext* context, TfLiteNode* node,
                      TfLitePoolParams* params, OpData* data,
                      const TfLiteTensor* input, TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                       \
  tflite::PoolParams op_params;                                          \
  op_params.stride_height = params->stride_height;                       \
  op_params.stride_width = params->stride_width;                         \
  op_params.filter_height = params->filter_height;                       \
  op_params.filter_width = params->filter_width;                         \
  op_params.padding_values.height = data->padding.height;                \
  op_params.padding_values.width = data->padding.width;                  \
  op_params.float_activation_min = activation_min;                       \
  op_params.float_activation_max = activation_max;                       \
  type::AveragePool(op_params, GetTensorShape(input),                    \
                    GetTensorData<float>(input), GetTensorShape(output), \
                    GetTensorData<float>(output))
void AverageEvalQuantizedUint8(TfLiteContext* context, TfLiteNode* node,
                               TfLitePoolParams* params, OpData* data,
                               const TfLiteTensor* input,
                               TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                         \
  tflite::PoolParams op_params;                                            \
  op_params.stride_height = params->stride_height;                         \
  op_params.stride_width = params->stride_width;                           \
  op_params.filter_height = params->filter_height;                         \
  op_params.filter_width = params->filter_width;                           \
  op_params.padding_values.height = data->padding.height;                  \
  op_params.padding_values.width = data->padding.width;                    \
  op_params.quantized_activation_min = activation_min;                     \
  op_params.quantized_activation_max = activation_max;                     \
  type::AveragePool(op_params, GetTensorShape(input),                      \
                    GetTensorData<uint8_t>(input), GetTensorShape(output), \
                    GetTensorData<uint8_t>(output))
void AverageEvalQuantizedInt8(TfLiteContext* context, TfLiteNode* node,
                              TfLitePoolParams* params, OpData* data,
                              const TfLiteTensor* input, TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                        \
  tflite::PoolParams op_params;                                           \
  op_params.stride_height = params->stride_height;                        \
  op_params.stride_width = params->stride_width;                          \
  op_params.filter_height = params->filter_height;                        \
  op_params.filter_width = params->filter_width;                          \
  op_params.padding_values.height = data->padding.height;                 \
  op_params.padding_values.width = data->padding.width;                   \
  op_params.quantized_activation_min = activation_min;                    \
  op_params.quantized_activation_max = activation_max;                    \
  type::AveragePool(op_params, GetTensorShape(input),                     \
                    GetTensorData<int8_t>(input), GetTensorShape(output), \
                    GetTensorData<int8_t>(output))
void AverageEvalQuantizedInt16(TfLiteContext* context, TfLiteNode* node,
                               TfLitePoolParams* params, OpData* data,
                               const TfLiteTensor* input,
                               TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                         \
  tflite::PoolParams op_params;                                            \
  op_params.stride_height = params->stride_height;                         \
  op_params.stride_width = params->stride_width;                           \
  op_params.filter_height = params->filter_height;                         \
  op_params.filter_width = params->filter_width;                           \
  op_params.padding_values.height = data->padding.height;                  \
  op_params.padding_values.width = data->padding.width;                    \
  op_params.quantized_activation_min = activation_min;                     \
  op_params.quantized_activation_max = activation_max;                     \
  type::AveragePool(op_params, GetTensorShape(input),                      \
                    GetTensorData<int16_t>(input), GetTensorShape(output), \
                    GetTensorData<int16_t>(output))
      AverageEvalFloat<kernel_type>(context, node, params, data, input, output);
      break;
      AverageEvalQuantizedUint8<kernel_type>(context, node, params, data, input,
                                             output);
      break;
      AverageEvalQuantizedInt8<kernel_type>(context, node, params, data, input,
                                            output);
      break;
      AverageEvalQuantizedInt16<kernel_type>(context, node, params, data, input,
                                             output);
      break;
Fixed code:   bool reference_success = reference_integer_ops::AveragePool(
      params, input_shape, input_data, output_shape,
      reference_averagePool_output.data());
  bool optimized_success = optimized_integer_ops::AveragePool(
      params, input_shape, input_data, output_shape,
      optimized_averagePool_output.data());
  EXPECT_TRUE(reference_success);
  EXPECT_TRUE(optimized_success);
inline bool AveragePool(const PoolParams& params,
          if (filter_count == 0) return false;
  return true;
inline bool AveragePool(const float* input_data, const Dims<4>& input_dims,
  return AveragePool(params, DimsToShape(input_dims), input_data,
                     DimsToShape(output_dims), output_data);
bool AveragePool(const float* input_data, const Dims<4>& input_dims,
  return AveragePool(input_data, input_dims, stride_width, stride_height,
                     pad_width, pad_height, kwidth, kheight,
                     output_activation_min, output_activation_max, output_data,
                     output_dims);
bool AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
                         pad_height, filter_width, filter_height, output_data,
                         output_dims);
inline bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  return AveragePool(params, DimsToShape(input_dims), input_data,
                     DimsToShape(output_dims), output_data);
bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  return AveragePool(input_data, input_dims, stride_width, stride_height,
                     pad_width, pad_height, filter_width, filter_height,
                     output_activation_min, output_activation_max, output_data,
                     output_dims);
bool AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
                         pad_height, filter_width, filter_height,
                         output_activation_min, output_activation_max,
                         output_data, output_dims);
inline bool AveragePool(const PoolParams& params,
  if (stride_height == 0) return false;
  if (stride_width == 0) return false;


  return true;
inline bool AveragePool(const PoolParams& params,
          if (filter_count == 0) return false;
  return true;
inline bool AveragePool(const PoolParams& params,
          if (filter_count == 0) return false;
  return true;
inline bool AveragePool(const PoolParams& params,
          if (filter_count == 0) return false;
  return true;
inline bool AveragePool(const float* input_data, const Dims<4>& input_dims,
  return AveragePool(params, DimsToShape(input_dims), input_data,
                     DimsToShape(output_dims), output_data);
bool AveragePool(const float* input_data, const Dims<4>& input_dims,
  return AveragePool(input_data, input_dims, stride_width, stride_height,
                     pad_width, pad_height, kwidth, kheight,
                     output_activation_min, output_activation_max, output_data,
                     output_dims);
bool AveragePool(const float* input_data, const Dims<4>& input_dims, int stride,
  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
                         pad_height, filter_width, filter_height, output_data,
                         output_dims);
inline bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  return AveragePool(params, DimsToShape(input_dims), input_data,
                     DimsToShape(output_dims), output_data);
bool AveragePool(const uint8* input_data, const Dims<4>& input_dims,
  return AveragePool(input_data, input_dims, stride_width, stride_height,
                     pad_width, pad_height, filter_width, filter_height,
                     output_activation_min, output_activation_max, output_data,
                     output_dims);
bool AveragePool(const uint8* input_data, const Dims<4>& input_dims, int stride,
  return AveragePool<Ac>(input_data, input_dims, stride, stride, pad_width,
                         pad_height, filter_width, filter_height,
                         output_activation_min, output_activation_max,
                         output_data, output_dims);
inline bool AveragePool(const PoolParams& params,
          if (filter_count == 0) return false;
  return true;
inline bool AveragePool(const PoolParams& params,
          if (filter_count == 0) return false;
  return true;
TfLiteStatus AverageEvalFloat(TfLiteContext* context, TfLiteNode* node,
                              TfLitePoolParams* params, OpData* data,
                              const TfLiteTensor* input, TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                            \
  tflite::PoolParams op_params;                                               \
  op_params.stride_height = params->stride_height;                            \
  op_params.stride_width = params->stride_width;                              \
  op_params.filter_height = params->filter_height;                            \
  op_params.filter_width = params->filter_width;                              \
  op_params.padding_values.height = data->padding.height;                     \
  op_params.padding_values.width = data->padding.width;                       \
  op_params.float_activation_min = activation_min;                            \
  op_params.float_activation_max = activation_max;                            \
  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
                                            GetTensorData<float>(input),      \
                                            GetTensorShape(output),           \
                                            GetTensorData<float>(output)))
  return kTfLiteOk;
TfLiteStatus AverageEvalQuantizedUint8(TfLiteContext* context, TfLiteNode* node,
                                       TfLitePoolParams* params, OpData* data,
                                       const TfLiteTensor* input,
                                       TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                            \
  tflite::PoolParams op_params;                                               \
  op_params.stride_height = params->stride_height;                            \
  op_params.stride_width = params->stride_width;                              \
  op_params.filter_height = params->filter_height;                            \
  op_params.filter_width = params->filter_width;                              \
  op_params.padding_values.height = data->padding.height;                     \
  op_params.padding_values.width = data->padding.width;                       \
  op_params.quantized_activation_min = activation_min;                        \
  op_params.quantized_activation_max = activation_max;                        \
  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
                                            GetTensorData<uint8_t>(input),    \
                                            GetTensorShape(output),           \
                                            GetTensorData<uint8_t>(output)))
  return kTfLiteOk;
TfLiteStatus AverageEvalQuantizedInt8(TfLiteContext* context, TfLiteNode* node,
                                      TfLitePoolParams* params, OpData* data,
                                      const TfLiteTensor* input,
                                      TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                            \
  tflite::PoolParams op_params;                                               \
  op_params.stride_height = params->stride_height;                            \
  op_params.stride_width = params->stride_width;                              \
  op_params.filter_height = params->filter_height;                            \
  op_params.filter_width = params->filter_width;                              \
  op_params.padding_values.height = data->padding.height;                     \
  op_params.padding_values.width = data->padding.width;                       \
  op_params.quantized_activation_min = activation_min;                        \
  op_params.quantized_activation_max = activation_max;                        \
  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
                                            GetTensorData<int8_t>(input),     \
                                            GetTensorShape(output),           \
                                            GetTensorData<int8_t>(output)))
  return kTfLiteOk;
TfLiteStatus AverageEvalQuantizedInt16(TfLiteContext* context, TfLiteNode* node,
                                       TfLitePoolParams* params, OpData* data,
                                       const TfLiteTensor* input,
                                       TfLiteTensor* output) {
#define TF_LITE_AVERAGE_POOL(type)                                            \
  tflite::PoolParams op_params;                                               \
  op_params.stride_height = params->stride_height;                            \
  op_params.stride_width = params->stride_width;                              \
  op_params.filter_height = params->filter_height;                            \
  op_params.filter_width = params->filter_width;                              \
  op_params.padding_values.height = data->padding.height;                     \
  op_params.padding_values.width = data->padding.width;                       \
  op_params.quantized_activation_min = activation_min;                        \
  op_params.quantized_activation_max = activation_max;                        \
  TF_LITE_ENSURE(context, type::AveragePool(op_params, GetTensorShape(input), \
                                            GetTensorData<int16_t>(input),    \
                                            GetTensorShape(output),           \
                                            GetTensorData<int16_t>(output)))
  return kTfLiteOk;
      return AverageEvalFloat<kernel_type>(context, node, params, data, input,
                                           output);
      return AverageEvalQuantizedUint8<kernel_type>(context, node, params, data,
                                                    input, output);
      return AverageEvalQuantizedInt8<kernel_type>(context, node, params, data,
                                                   input, output);
      return AverageEvalQuantizedInt16<kernel_type>(context, node, params, data,
                                                    input, output);