Vulnerability: FPE in TFLite division operations ### Impact
The implementation of division in TFLite is [vulnerable to a division by 0 error](https://github.com/tensorflow/tensorflow/blob/460e000de3a83278fb00b61a16d161b1964f15f4/tensorflow/lite/kernels/div.cc)

There is no check that the divisor tensor does not contain zero elements.

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

The fix will be included in TensorFlow 2.6.0. We will also cherrypick this commit on TensorFlow 2.5.1, TensorFlow 2.4.3, and TensorFlow 2.3.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-rhrq-64mq-hf9h
CWE: CWE-369
Severity score: 5.5
Project: https://github.com/tensorflow/tensorflow
Published: 2021-08-25
File: tensorflow/lite/kernels/div.cc
Commit message: Prevent a division by 0 in division ops.

PiperOrigin-RevId: 385223169
Change-Id: Ia4228960b5d2aa44480385f74bdd70d21a3613c3
Commit author: Mihai Maruseac

Vulnerable version (before fix):
 TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {   TF_LITE_ENSURE_OK(context,                     GetOutputSafe(context, node, kOutputTensor, &output));    if (output->type == kTfLiteFloat32 || output->type == kTfLiteInt32) {     EvalDiv<kernel_type>(context, node, params, data, input1, input2, output);   } else if (output->type == kTfLiteUInt8) {     TF_LITE_ENSURE_OK(         context, EvalQuantized<kernel_type>(context, node, params, data, input1,                                             input2, output)); TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {         output->type);     return kTfLiteError;   }    return kTfLiteOk; }

Fixed version (after fix):
 TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {   TF_LITE_ENSURE_OK(context,                     GetOutputSafe(context, node, kOutputTensor, &output));    // TODO(b/193904910): This can written with C++ templates #define TF_LITE_CHECK_DIV_NON_ZERO(data_type)                       \   const auto* input2_data = GetTensorData<data_type>(input2);       \   const size_t input2_elements = input2->bytes / sizeof(data_type); \   for (size_t i = 0; i < input2_elements; i++) {                    \     TF_LITE_ENSURE(context, input2_data[i] != 0);                   \   }    if (output->type == kTfLiteFloat32) {     // Div by zero seems ok in this case, just like in TF case infinities are     // returned. So we don't do a check at this point.     EvalDiv<kernel_type>(context, node, params, data, input1, input2, output);   } else if (output->type == kTfLiteInt32) {     TF_LITE_CHECK_DIV_NON_ZERO(int32_t);     EvalDiv<kernel_type>(context, node, params, data, input1, input2, output);   } else if (output->type == kTfLiteUInt8) {     TF_LITE_CHECK_DIV_NON_ZERO(uint8_t);     TF_LITE_ENSURE_OK(         context, EvalQuantized<kernel_type>(context, node, params, data, input1,                                             input2, output)); TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {         output->type);     return kTfLiteError;   } #undef TF_LITE_CHECK_DIV_NON_ZERO    return kTfLiteOk; }

Patch:
patch: @@ -216,9 +216,23 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
   TF_LITE_ENSURE_OK(context,
                     GetOutputSafe(context, node, kOutputTensor, &output));
 
-  if (output->type == kTfLiteFloat32 || output->type == kTfLiteInt32) {
+  // TODO(b/193904910): This can written with C++ templates
+#define TF_LITE_CHECK_DIV_NON_ZERO(data_type)                       \
+  const auto* input2_data = GetTensorData<data_type>(input2);       \
+  const size_t input2_elements = input2->bytes / sizeof(data_type); \
+  for (size_t i = 0; i < input2_elements; i++) {                    \
+    TF_LITE_ENSURE(context, input2_data[i] != 0);                   \
+  }
+
+  if (output->type == kTfLiteFloat32) {
+    // Div by zero seems ok in this case, just like in TF case infinities are
+    // returned. So we don't do a check at this point.
+    EvalDiv<kernel_type>(context, node, params, data, input1, input2, output);
+  } else if (output->type == kTfLiteInt32) {
+    TF_LITE_CHECK_DIV_NON_ZERO(int32_t);
     EvalDiv<kernel_type>(context, node, params, data, input1, input2, output);
   } else if (output->type == kTfLiteUInt8) {
+    TF_LITE_CHECK_DIV_NON_ZERO(uint8_t);
     TF_LITE_ENSURE_OK(
         context, EvalQuantized<kernel_type>(context, node, params, data, input1,
                                             input2, output));
@@ -229,6 +243,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
         output->type);
     return kTfLiteError;
   }
+#undef TF_LITE_CHECK_DIV_NON_ZERO
 
   return kTfLiteOk;
 }
path: tensorflow/lite/kernels/div.cc