Vulnerability: Out of bounds write in Tensorflow ### Impact
TensorFlow is vulnerable to a heap OOB write in [Grappler](https://github.com/tensorflow/tensorflow/blob/a1320ec1eac186da1d03f033109191f715b2b130/tensorflow/core/grappler/costs/graph_properties.cc#L1132-L1141):

```cc
Status SetUnknownShape(const NodeDef* node, int output_port) {
  shape_inference::ShapeHandle shape = 
      GetUnknownOutputShape(node, output_port);
  InferenceContext* ctx = GetContext(node);
  if (ctx == nullptr) {
    return errors::InvalidArgument("Missing context");
  }
  ctx->set_output(output_port, shape);
  return Status::OK();
}
```

The [`set_output`](https://github.com/tensorflow/tensorflow/blob/a1320ec1eac186da1d03f033109191f715b2b130/tensorflow/core/framework/shape_inference.h#L394) function writes to an array at the specified index:

```cc
void set_output(int idx, ShapeHandle shape) { outputs_.at(idx) = shape; }
```

Hence, this gives a malicious user a write primitive.

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

The fix will be included in TensorFlow 2.8.0. We will also cherrypick this commit on TensorFlow 2.7.1, TensorFlow 2.6.3, and TensorFlow 2.5.3, 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.
Vulnerability ID: GHSA-5qw5-89mw-wcg2
CWE: CWE-787
Severity score: 8.8
Project: https://github.com/tensorflow/tensorflow
Published: 2022-02-09
File: tensorflow/core/grappler/costs/graph_properties.cc
Commit message: Prevent a crash due to heap OOB write in grappler.

PiperOrigin-RevId: 408318417
Change-Id: If095feb8c001e3a8ac4a85b7387b81e8309df47d
Commit author: Mihai Maruseac

Vulnerable version (before fix):
 class SymbolicShapeRefiner {         GetUnknownOutputShape(node, output_port);     InferenceContext* ctx = GetContext(node);     if (ctx == nullptr) {       return errors::InvalidArgument("Missing context");     }     ctx->set_output(output_port, shape);     return Status::OK();

Fixed version (after fix):
 class SymbolicShapeRefiner {         GetUnknownOutputShape(node, output_port);     InferenceContext* ctx = GetContext(node);     if (ctx == nullptr) {       return errors::InvalidArgument("SetUnknownShape: Missing context");     }     if (output_port < 0 || output_port >= ctx->num_outputs()) {       return errors::InvalidArgument(           "SetUnknownShape: output_port must be in [0, ", ctx->num_outputs(),           ") but was ", output_port);     }     ctx->set_output(output_port, shape);     return Status::OK();

Patch:
patch: @@ -1134,7 +1134,12 @@ class SymbolicShapeRefiner {
         GetUnknownOutputShape(node, output_port);
     InferenceContext* ctx = GetContext(node);
     if (ctx == nullptr) {
-      return errors::InvalidArgument("Missing context");
+      return errors::InvalidArgument("SetUnknownShape: Missing context");
+    }
+    if (output_port < 0 || output_port >= ctx->num_outputs()) {
+      return errors::InvalidArgument(
+          "SetUnknownShape: output_port must be in [0, ", ctx->num_outputs(),
+          ") but was ", output_port);
     }
     ctx->set_output(output_port, shape);
     return Status::OK();
path: tensorflow/core/grappler/costs/graph_properties.cc