CVE-2021-37636: Divide By Zero (CWE-369)
value: TensorFlow is an end-to-end open source platform for machine learning. In affected versions the implementation of `tf.raw_ops.SparseDenseCwiseDiv` is vulnerable to a division by 0 error. The [implementation](https://github.com/tensorflow/tensorflow/blob/a1bc56203f21a5a4995311825ffaba7a670d7747/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc#L56) uses a common class for all binary operations but fails to treat the division by 0 case separately. We have patched the issue in GitHub commit d9204be9f49520cdaaeb2541d1dc5187b23f31d9. 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.
CWE description: The product divides a value by zero.
CVSS v3 base score: 5.5
Published: 2021-08-12T18:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
Commit date: 2021-07-09 18:31:46 -0700
Commit message: Disallow division by zero FPE in tf.raw_ops.SparseDenseCwiseDiv

PiperOrigin-RevId: 383959809
Change-Id: Ibe88458bdf66a686c93e354b8255dec94285c560

Diff: diff --git a/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc b/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
index dac4a3d3e6bfc..dda05dbc3b8cb 100644
--- a/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
+++ b/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
@@ -112,11 +112,14 @@ class SparseDenseBinaryOpShared : public OpKernel {
     OP_REQUIRES_OK(ctx,
                    ctx->allocate_output(0, TensorShape({nnz}), &output_values));
     OP_REQUIRES_OK(
         ctx, ctx->allocate_temp(DataTypeToEnum<T>::value, TensorShape({nnz}),
                                 &dense_gathered));
-
+    bool op_is_div = false;
+    if (absl::StrContains(ctx->op_kernel().type_string_view(), "Div")) {
+      op_is_div = true;
+    }
     // Pulls relevant entries from the dense side, with reshape and broadcasting
     // *of the dense side* taken into account.  Use a TensorRef to avoid blowing
     // up memory.
     //
     // We can directly use the sparse indices to look up dense side, because
@@ -141,10 +144,16 @@ class SparseDenseBinaryOpShared : public OpKernel {
       OP_REQUIRES(                                                             \
           ctx, indices_valid,                                                  \
           errors::InvalidArgument("Provided indices are out-of-bounds w.r.t. " \
                                   "dense side with broadcasted shape"));       \
       dense_gathered_flat(i) = rhs_ref.coeff(idx);                             \
+      if (op_is_div) {                                                         \
+        OP_REQUIRES(ctx, dense_gathered_flat(i) != 0,                          \
+                    errors::InvalidArgument(                                   \
+                        "SparseDenseCwiseDiv cannot divide by zero,"           \
+                        "but input dense tensor contains zero "));             \
+      }                                                                        \
     }                                                                          \
     break;                                                                     \
   }
 
       CASE(1);

Fixed code:     bool op_is_div = false;
    if (absl::StrContains(ctx->op_kernel().type_string_view(), "Div")) {
      op_is_div = true;
    }
      if (op_is_div) {                                                         \
        OP_REQUIRES(ctx, dense_gathered_flat(i) != 0,                          \
                    errors::InvalidArgument(                                   \
                        "SparseDenseCwiseDiv cannot divide by zero,"           \
                        "but input dense tensor contains zero "));             \
      }                                                                        \