Vulnerability: Null pointer dereference in TFLite's `Reshape` operator ### Impact
The fix for [CVE-2020-15209](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15209) missed the case when the target shape of `Reshape` operator is given by the elements of a 1-D tensor. As such, the [fix for the vulnerability](https://github.com/tensorflow/tensorflow/blob/9c1dc920d8ffb4893d6c9d27d1f039607b326743/tensorflow/lite/core/subgraph.cc#L1062-L1074) allowed passing a null-buffer-backed tensor with a 1D shape:

```cc
if (tensor->data.raw == nullptr && tensor->bytes > 0) {
  if (registration.builtin_code == kTfLiteBuiltinReshape && i == 1) {
    // In general, having a tensor here with no buffer will be an error.
    // However, for the reshape operator, the second input tensor is only
    // used for the shape, not for the data. Thus, null buffer is ok.
    continue;
  } else {
    // In all other cases, we need to return an error as otherwise we will
    // trigger a null pointer dereference (likely).
    ReportError("Input tensor %d lacks data", tensor_index);
    return kTfLiteError;
  }
}
```

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

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 members of the Aivul Team from Qihoo 360.
Vulnerability ID: GHSA-jjr8-m8g8-p6wv
CWE: CWE-476
Severity score: 4.4
Project: https://github.com/tensorflow/tensorflow
Published: 2021-05-21
File: tensorflow/lite/core/subgraph.cc
Commit message: Prevent a null pointer dereference in TFLite.

PiperOrigin-RevId: 370800353
Change-Id: Ic9c9712ce5c6e384c954dcd640a5bd9ff05c9a05
Commit author: Mihai Maruseac

Vulnerable version (before fix):
 TfLiteStatus Subgraph::Invoke() {         TF_LITE_ENSURE_STATUS(EnsureTensorDataIsReadable(tensor_index));       }       if (tensor->data.raw == nullptr && tensor->bytes > 0) {         if (registration.builtin_code == kTfLiteBuiltinReshape && i == 1) {           // In general, having a tensor here with no buffer will be an error.           // However, for the reshape operator, the second input tensor is only           // used for the shape, not for the data. Thus, null buffer is ok.           continue;         } else {           // In all other cases, we need to return an error as otherwise we will

Fixed version (after fix):
 TfLiteStatus Subgraph::Invoke() {         TF_LITE_ENSURE_STATUS(EnsureTensorDataIsReadable(tensor_index));       }       if (tensor->data.raw == nullptr && tensor->bytes > 0) {         if (registration.builtin_code == kTfLiteBuiltinReshape && i == 1 &&             tensor->dims->size != 1) {           // In general, having a tensor here with no buffer will be an error.           // However, for the reshape operator, the second input tensor is           // sometimes only used for the shape, not for the data. Thus, null           // buffer is ok in this situation.           // The situation where null buffer is not ok for reshape operator is           // only when there are 2 inputs given to the node and the one           // corresponding to the shape (i == 1) is a vector that contains all           // dimensions. See `GetOutputShape()` function in           // `tensorflow/lite/kernels/reshape.cc`           continue;         } else {           // In all other cases, we need to return an error as otherwise we will

Patch:
patch: @@ -1060,10 +1060,17 @@ TfLiteStatus Subgraph::Invoke() {
         TF_LITE_ENSURE_STATUS(EnsureTensorDataIsReadable(tensor_index));
       }
       if (tensor->data.raw == nullptr && tensor->bytes > 0) {
-        if (registration.builtin_code == kTfLiteBuiltinReshape && i == 1) {
+        if (registration.builtin_code == kTfLiteBuiltinReshape && i == 1 &&
+            tensor->dims->size != 1) {
           // In general, having a tensor here with no buffer will be an error.
-          // However, for the reshape operator, the second input tensor is only
-          // used for the shape, not for the data. Thus, null buffer is ok.
+          // However, for the reshape operator, the second input tensor is
+          // sometimes only used for the shape, not for the data. Thus, null
+          // buffer is ok in this situation.
+          // The situation where null buffer is not ok for reshape operator is
+          // only when there are 2 inputs given to the node and the one
+          // corresponding to the shape (i == 1) is a vector that contains all
+          // dimensions. See `GetOutputShape()` function in
+          // `tensorflow/lite/kernels/reshape.cc`
           continue;
         } else {
           // In all other cases, we need to return an error as otherwise we will
path: tensorflow/lite/core/subgraph.cc