Vulnerability: Division by 0 in `FractionalAvgPool` ### Impact
An attacker can cause a runtime division by zero error and denial of service in `tf.raw_ops.FractionalAvgPool`:

```python
import tensorflow as tf

value = tf.constant([60], shape=[1, 1, 1, 1], dtype=tf.int32)
pooling_ratio = [1.0, 1.0000014345305555, 1.0, 1.0]
pseudo_random = False
overlapping = False
deterministic = False
seed = 0
seed2 = 0

tf.raw_ops.FractionalAvgPool(
  value=value, pooling_ratio=pooling_ratio, pseudo_random=pseudo_random,
  overlapping=overlapping, deterministic=deterministic, seed=seed, seed2=seed2)
```

This is because the [implementation](https://github.com/tensorflow/tensorflow/blob/acc8ee69f5f46f92a3f1f11230f49c6ac266f10c/tensorflow/core/kernels/fractional_avg_pool_op.cc#L85-L89) computes a divisor quantity by dividing two user controlled values:

```cc                     
for (int i = 0; i < tensor_in_and_out_dims; ++i) {
  output_size[i] = static_cast<int>(std::floor(input_size[i] / pooling_ratio_[i]));
  DCHECK_GT(output_size[i], 0); 
} 
``` 
    
The user controls the values of `input_size[i]` and `pooling_ratio_[i]` (via the `value.shape()` and `pooling_ratio` arguments). If the value in `input_size[i]` is smaller than the `pooling_ratio_[i]`, then the floor operation results in `output_size[i]` being 0. The `DCHECK_GT` line is a no-op outside of debug mode, so in released versions of TF this does not trigger.

Later, these computed values [are used as arguments](https://github.com/tensorflow/tensorflow/blob/acc8ee69f5f46f92a3f1f11230f49c6ac266f10c/tensorflow/core/kernels/fractional_avg_pool_op.cc#L96-L99) to [`GeneratePoolingSequence`](https://github.com/tensorflow/tensorflow/blob/acc8ee69f5f46f92a3f1f11230f49c6ac266f10c/tensorflow/core/kernels/fractional_pool_common.cc#L100-L108). There, the first computation is a division in a modulo operation:

```cc
std::vector<int64> GeneratePoolingSequence(int input_length, int output_length,
                                           GuardedPhiloxRandom* generator,
                                           bool pseudo_random) {
  ...
  if (input_length % output_length == 0) {
    diff = std::vector<int64>(output_length, input_length / output_length);
  }
  ...
}
```

Since `output_length` can be 0, this results in runtime crashing.

### Patches
We have patched the issue in GitHub commit [548b5eaf23685d86f722233d8fbc21d0a4aecb96](https://github.com/tensorflow/tensorflow/commit/548b5eaf23685d86f722233d8fbc21d0a4aecb96).

The fix will be included in TensorFlow 2.5.0. We will also cherrypick this commit on TensorFlow 2.4.2, TensorFlow 2.3.3, TensorFlow 2.2.3 and TensorFlow 2.1.4, as these are also affected and still in supported range.

### For more information
Please consult [our security guide](https://github.com/tensorflow/tensorflow/blob/master/SECURITY.md) for more information regarding the security model and how to contact us with issues and questions.

### Attribution
This vulnerability has been reported by Ying Wang and Yakun Zhang of Baidu X-Team.
Vulnerability ID: GHSA-f78g-q7r4-9wcv
CWE: CWE-369
Severity score: 2.5
Project: https://github.com/tensorflow/tensorflow
Published: 2021-05-21
File: tensorflow/core/kernels/fractional_avg_pool_op.cc
Commit message: Fix divide by zero error in `fractional_pool_common.cc`.

PiperOrigin-RevId: 371126221
Change-Id: Iea4b2f363aaeb116ab460e3bc592c687484af344
Commit author: Laura Pak

Vulnerable version (before fix):
 class FractionalAvgPoolOp : public OpKernel {     std::vector<int> output_size(tensor_in_and_out_dims);     for (int i = 0; i < tensor_in_and_out_dims; ++i) {       input_size[i] = tensor_in.dim_size(i);     }     // Output size.     for (int i = 0; i < tensor_in_and_out_dims; ++i) {

Fixed version (after fix):
 class FractionalAvgPoolOp : public OpKernel {     std::vector<int> output_size(tensor_in_and_out_dims);     for (int i = 0; i < tensor_in_and_out_dims; ++i) {       input_size[i] = tensor_in.dim_size(i);       OP_REQUIRES(           context, pooling_ratio_[i] <= input_size[i],           errors::InvalidArgument(               "Pooling ratio cannot be bigger than input tensor dim size."));     }     // Output size.     for (int i = 0; i < tensor_in_and_out_dims; ++i) {

Patch:
patch: @@ -80,6 +80,10 @@ class FractionalAvgPoolOp : public OpKernel {
     std::vector<int> output_size(tensor_in_and_out_dims);
     for (int i = 0; i < tensor_in_and_out_dims; ++i) {
       input_size[i] = tensor_in.dim_size(i);
+      OP_REQUIRES(
+          context, pooling_ratio_[i] <= input_size[i],
+          errors::InvalidArgument(
+              "Pooling ratio cannot be bigger than input tensor dim size."));
     }
     // Output size.
     for (int i = 0; i < tensor_in_and_out_dims; ++i) {
path: tensorflow/core/kernels/fractional_avg_pool_op.cc