Vulnerability: Heap buffer overflow in `RaggedBinCount` ### Impact
If the `splits` argument of `RaggedBincount` does not specify a valid [`SparseTensor`](https://www.tensorflow.org/api_docs/python/tf/sparse/SparseTensor), then an attacker can trigger a heap buffer overflow:

```python
import tensorflow as tf
tf.raw_ops.RaggedBincount(splits=[0], values=[1,1,1,1,1], size=5, weights=[1,2,3,4], binary_output=False)
```

This will cause a read from outside the bounds of the `splits` tensor buffer in the [implementation of the `RaggedBincount` op](https://github.com/tensorflow/tensorflow/blob/8b677d79167799f71c42fd3fa074476e0295413a/tensorflow/core/kernels/bincount_op.cc#L430-L433):

```cc
    for (int idx = 0; idx < num_values; ++idx) {
      while (idx >= splits(batch_idx)) {
        batch_idx++;
      }
      ...
    }
```

Before the `for` loop, `batch_idx` is set to 0. The user controls the `splits` array, making it contain only one element, 0. Thus, the code in the `while` loop would increment `batch_idx` and then try to read `splits(1)`, which is outside of bounds.

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

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

### 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 members of the Aivul Team from Qihoo 360.
Vulnerability ID: GHSA-4278-2v5v-65r4
CWE: CWE-787
Severity score: 2.5
Project: https://github.com/tensorflow/tensorflow
Published: 2021-05-21
File: tensorflow/core/kernels/bincount_op.cc
Commit message: Fix an invalid address vulnerability in `tf.raw_ops.RaggedBincount`.

PiperOrigin-RevId: 368293153
Change-Id: I4b4e493d3fd05e7dc55a55de3a041a80a4f275c3
Commit author: Amit Patankar

Vulnerable version (before fix):
 class RaggedBincountOp : public OpKernel {     int num_values = values.size();     int batch_idx = 0;      Tensor* out_t;     OP_REQUIRES_OK(         ctx, ctx->allocate_output(0, TensorShape({num_rows, size}), &out_t));

Fixed version (after fix):
 class RaggedBincountOp : public OpKernel {     int num_values = values.size();     int batch_idx = 0;      OP_REQUIRES(ctx, splits(0) == 0,                 errors::InvalidArgument("Splits must start with 0, not with ",                                         splits(0)));      OP_REQUIRES(ctx, splits(num_rows) == num_values,                 errors::InvalidArgument(                     "Splits must end with the number of values, got ",                     splits(num_rows), " instead of ", num_values));      Tensor* out_t;     OP_REQUIRES_OK(         ctx, ctx->allocate_output(0, TensorShape({num_rows, size}), &out_t));

Patch:
patch: @@ -420,6 +420,15 @@ class RaggedBincountOp : public OpKernel {
     int num_values = values.size();
     int batch_idx = 0;
 
+    OP_REQUIRES(ctx, splits(0) == 0,
+                errors::InvalidArgument("Splits must start with 0, not with ",
+                                        splits(0)));
+
+    OP_REQUIRES(ctx, splits(num_rows) == num_values,
+                errors::InvalidArgument(
+                    "Splits must end with the number of values, got ",
+                    splits(num_rows), " instead of ", num_values));
+
     Tensor* out_t;
     OP_REQUIRES_OK(
         ctx, ctx->allocate_output(0, TensorShape({num_rows, size}), &out_t));
path: tensorflow/core/kernels/bincount_op.cc