Vulnerability: Heap OOB in `SparseBinCount` ### Impact
The [implementation](https://github.com/tensorflow/tensorflow/blob/e71b86d47f8bc1816bf54d7bddc4170e47670b97/tensorflow/core/kernels/bincount_op.cc#L353-L417) of `SparseBinCount` is vulnerable to a heap OOB:

```python
import tensorflow as tf
  
  
tf.raw_ops.SparseBincount(
  indices=[[0],[1],[2]]
  values=[0,-10000000]
  dense_shape=[1,1]
  size=[1]
  weights=[3,2,1]
  binary_output=False)
```

This is because of missing validation between the elements of the `values` argument and the shape of the sparse output:


```cc
for (int64_t i = 0; i < indices_mat.dimension(0); ++i) {
  const int64_t batch = indices_mat(i, 0);
  const Tidx bin = values(i);
  ...
  out(batch, bin) = ...;
}
```

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

The fix will be included in TensorFlow 2.7.0. We will also cherrypick this commit on TensorFlow 2.6.1, TensorFlow 2.5.2, and TensorFlow 2.4.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 members of the Aivul Team from Qihoo 360.
Vulnerability ID: GHSA-374m-jm66-3vj8
CWE: CWE-125
Severity score: 7.1
Project: https://github.com/tensorflow/tensorflow
Published: 2021-11-10
File: tensorflow/core/kernels/bincount_op.cc
Commit message: Prevent out-of-bound accesses in SparseBincount.

PiperOrigin-RevId: 399918616
Change-Id: I11d154f4444d3fde1f09c5c40628b8671791a30d
Commit author: Penporn Koanantakool

Vulnerable version (before fix):
 class SparseBincountOp : public OpKernel {       for (int64_t i = 0; i < indices_mat.dimension(0); ++i) {         const int64_t batch = indices_mat(i, 0);         const Tidx bin = values(i);         if (bin < size) {           if (binary_output_) {             out(batch, bin) = T(1);

Fixed version (after fix):
 class SparseBincountOp : public OpKernel {       for (int64_t i = 0; i < indices_mat.dimension(0); ++i) {         const int64_t batch = indices_mat(i, 0);         const Tidx bin = values(i);         OP_REQUIRES(             ctx, batch < out.dimension(0),             errors::InvalidArgument("Index out of bound. `batch` (", batch,                                     ") must be less than the dimension size (",                                     out.dimension(0), ")."));         OP_REQUIRES(             ctx, bin < out.dimension(1),             errors::InvalidArgument("Index out ouf bound. `bin` (", bin,                                     ") must be less then the dimension size (",                                     out.dimension(1), ")."));         if (bin < size) {           if (binary_output_) {             out(batch, bin) = T(1);

Patch:
patch: @@ -405,6 +405,16 @@ class SparseBincountOp : public OpKernel {
       for (int64_t i = 0; i < indices_mat.dimension(0); ++i) {
         const int64_t batch = indices_mat(i, 0);
         const Tidx bin = values(i);
+        OP_REQUIRES(
+            ctx, batch < out.dimension(0),
+            errors::InvalidArgument("Index out of bound. `batch` (", batch,
+                                    ") must be less than the dimension size (",
+                                    out.dimension(0), ")."));
+        OP_REQUIRES(
+            ctx, bin < out.dimension(1),
+            errors::InvalidArgument("Index out ouf bound. `bin` (", bin,
+                                    ") must be less then the dimension size (",
+                                    out.dimension(1), ")."));
         if (bin < size) {
           if (binary_output_) {
             out(batch, bin) = T(1);
path: tensorflow/core/kernels/bincount_op.cc