Publicus/cvefixes-security-ir-graphrag huggingface dataset:
CVE-2021-37688: NULL Pointer Dereference (CWE-476)
value: TensorFlow is an end-to-end open source platform for machine learning. In affected versions an attacker can craft a TFLite model that would trigger a null pointer dereference, which would result in a crash and denial of service. The [implementation](https://github.com/tensorflow/tensorflow/blob/149562d49faa709ea80df1d99fc41d005b81082a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h#L268-L285) unconditionally dereferences a pointer. We have patched the issue in GitHub commit 15691e456c7dc9bd6be203b09765b063bf4a380c. 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 dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 5.5
Published: 2021-08-12T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C
Files changed: tensorflow/lite/kernels/internal/optimized/optimized_ops.h
Commit date: 2021-07-27 18:47:05 -0700
Commit message: Prevent dereferencing of null pointers in TFLite's `add.cc`.

PiperOrigin-RevId: 387244946
Change-Id: I56094233327fbd8439b92e1dbb1262176e00eeb9

Diff: diff --git a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h
index 241405a6bbae1..296b3923a257a 100644
--- a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h
+++ b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h
@@ -263,11 +263,11 @@ inline void BinaryBroadcastFiveFold(const ArithmeticParams& unswitched_params,
         }
       }
       // We have broadcast y2*y3*y4 of input2 data y1 times, and now move on.
       input2_data_reset = input2_data_ptr;
     }
-  } else {
+  } else if (input1_data_ptr != nullptr) {
     // Special case of y4 == 1, in which the innermost loop is a single
     // element and can be combined with the next (y3) as an inner broadcast.
     //
     // Note that this handles the case of pure scalar broadcast when
     // y0 == y1 == y2 == 1. With low overhead it handles cases such as scalar

Vulnerable code:   } else {
Fixed code:   } else if (input1_data_ptr != nullptr) {
CVE-2021-37689: NULL Pointer Dereference (CWE-476)
value: TensorFlow is an end-to-end open source platform for machine learning. In affected versions an attacker can craft a TFLite model that would trigger a null pointer dereference, which would result in a crash and denial of service. This is caused by the MLIR optimization of `L2NormalizeReduceAxis` operator. The [implementation](https://github.com/tensorflow/tensorflow/blob/149562d49faa709ea80df1d99fc41d005b81082a/tensorflow/compiler/mlir/lite/transforms/optimize.cc#L67-L70) unconditionally dereferences a pointer to an iterator to a vector without checking that the vector has elements. We have patched the issue in GitHub commit d6b57f461b39fd1aa8c1b870f1b974aac3554955. 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 dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 5.5
Published: 2021-08-12T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/compiler/mlir/lite/transforms/optimize.cc
Commit date: 2021-07-27 16:32:11 -0700
Commit message: Prevent nullptr dereference in MLIR TFLite dialect/optimizer.

PiperOrigin-RevId: 387220762
Change-Id: Id136ef04bb3d36123b4685d316ae81a9ec924d6b

Diff: diff --git a/tensorflow/compiler/mlir/lite/transforms/optimize.cc b/tensorflow/compiler/mlir/lite/transforms/optimize.cc
index d457612bf70ee..6a8803d246159 100644
--- a/tensorflow/compiler/mlir/lite/transforms/optimize.cc
+++ b/tensorflow/compiler/mlir/lite/transforms/optimize.cc
@@ -66,10 +66,13 @@ namespace {
 constexpr char kRelu[] = "RELU";
 constexpr char kRelu6[] = "RELU6";
 constexpr char kRelu1[] = "RELU_N1_TO_1";
 
 bool L2NormalizeReduceAxis(Value sq_op, DenseElementsAttr axis) {
+  if (axis.getNumElements() == 0) {
+    return false;
+  }
   if (sq_op.getType().cast<ShapedType>().getRank() - 1 ==
           *axis.getValues<int>().begin() ||
       *axis.getValues<int>().begin() == -1) {
     return true;
   }

Fixed code:   if (axis.getNumElements() == 0) {
    return false;
  }
CVE-2021-37691: Divide By Zero (CWE-369)
value: TensorFlow is an end-to-end open source platform for machine learning. In affected versions an attacker can craft a TFLite model that would trigger a division by zero error in LSH [implementation](https://github.com/tensorflow/tensorflow/blob/149562d49faa709ea80df1d99fc41d005b81082a/tensorflow/lite/kernels/lsh_projection.cc#L118). We have patched the issue in GitHub commit 0575b640091680cfb70f4dd93e70658de43b94f9. The fix will be included in TensorFlow 2.6.0. We will also cherrypick thiscommit 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-12T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/lite/kernels/lsh_projection.cc
Commit date: 2021-07-27 16:50:05 -0700
Commit message: Prevent division by 0 in LSH projection.

PiperOrigin-RevId: 387225857
Change-Id: Iaeb572a763618c64f503e0026f6dd9fd769bf50c

Diff: diff --git a/tensorflow/lite/kernels/lsh_projection.cc b/tensorflow/lite/kernels/lsh_projection.cc
index 81f97ecf9a9ce..92a5ee556f724 100644
--- a/tensorflow/lite/kernels/lsh_projection.cc
+++ b/tensorflow/lite/kernels/lsh_projection.cc
@@ -26,11 +26,11 @@ limitations under the License.
 //     Computed bit vector is considered to be dense. Each output element is
 // either 0 or 1 that represents a bit.
 //
 // Input:
 //   Tensor[0]: Hash functions. Dim.size == 2, DataType: Float.
-//              Tensor[0].Dim[0]: Num of hash functions.
+//              Tensor[0].Dim[0]: Num of hash functions. Must be at least 1.
 //              Tensor[0].Dim[1]: Num of projected output bits generated by
 //                                each hash function.
 //   In sparse case, Tensor[0].Dim[1] + ceil( log2(Tensor[0].Dim[0] )) <= 32.
 //
 //   Tensor[1]: Input. Dim.size >= 1, No restriction on DataType.
@@ -80,10 +80,11 @@ TfLiteStatus Resize(TfLiteContext* context, TfLiteNode* node) {
   TF_LITE_ENSURE(context, SizeOfDimension(hash, 1) <= 32);
 
   const TfLiteTensor* input;
   TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, 1, &input));
   TF_LITE_ENSURE(context, NumDimensions(input) >= 1);
+  TF_LITE_ENSURE(context, SizeOfDimension(input, 0) >= 1);
 
   if (NumInputs(node) == 3) {
     const TfLiteTensor* weight;
     TF_LITE_ENSURE_OK(context, GetInputSafe(context, node, 2, &weight));
     TF_LITE_ENSURE_EQ(context, NumDimensions(weight), 1);

Vulnerable code: //              Tensor[0].Dim[0]: Num of hash functions.
Fixed code: //              Tensor[0].Dim[0]: Num of hash functions. Must be at least 1.
  TF_LITE_ENSURE(context, SizeOfDimension(input, 0) >= 1);
CVE-2021-37692: Improper Input Validation (CWE-20)
value: TensorFlow is an end-to-end open source platform for machine learning. In affected versions under certain conditions, Go code can trigger a segfault in string deallocation. For string tensors, `C.TF_TString_Dealloc` is called during garbage collection within a finalizer function. However, tensor structure isn't checked until encoding to avoid a performance penalty. The current method for dealloc assumes that encoding succeeded, but segfaults when a string tensor is garbage collected whose encoding failed (e.g., due to mismatched dimensions). To fix this, the call to set the finalizer function is deferred until `NewTensor` returns and, if encoding failed for a string tensor, deallocs are determined based on bytes written. We have patched the issue in GitHub commit 8721ba96e5760c229217b594f6d2ba332beedf22. The fix will be included in TensorFlow 2.6.0. We will also cherrypick this commit on TensorFlow 2.5.1, which is the other affected version.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
CVSS v3 base score: 5.5
Published: 2021-08-12T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Go
Files changed: tensorflow/go/tensor.go
Commit date: 2021-07-13 15:13:47 -0700
Commit message: Merge pull request #50508 from wamuir:fix-tstring-dealloc

PiperOrigin-RevId: 384557722
Change-Id: I72858edf72952fd4e7e0a1d9776c9408a7081d42

Diff: diff --cc tensorflow/go/tensor.go
index cfb389d472dfa,6c58aeb81ff48..0983e0411f0b2
--- a/tensorflow/go/tensor.go
+++ b/tensorflow/go/tensor.go
@@@ -512,19 -515,21 +515,21 @@@ func encodeTensorWithSlices(w *bytes.Bu
  		}
  		ptr := unsafe.Pointer(elt.Addr().Pointer())
  		return copyPtr(w, ptr, v.Len()*int(elt.Type().Size()))
  	}
  
+ 	n := 0
  	subShape := shape[1:]
  	for i := 0; i < v.Len(); i++ {
- 		err := encodeTensorWithSlices(w, v.Index(i), subShape)
+ 		j, err := encodeTensorWithSlices(w, v.Index(i), subShape)
  		if err != nil {
- 			return err
 -			return n+j, err
++			return n + j, err
  		}
+ 		n += j
  	}
  
- 	return nil
+ 	return n, nil
  }
  
  // It isn't safe to use reflect.SliceHeader as it uses a uintptr for Data and
  // this is not inspected by the garbage collector
  type sliceHeader struct {

Vulnerable code:  		err := encodeTensorWithSlices(w, v.Index(i), subShape)
 			return err
 	return nil
Fixed code:  	n := 0
 		j, err := encodeTensorWithSlices(w, v.Index(i), subShape)
+			return n + j, err
 		n += j
 	return n, nil
CVE-2021-41200: Reachable Assertion (CWE-617)
value: TensorFlow is an open source platform for machine learning. In affected versions if `tf.summary.create_file_writer` is called with non-scalar arguments code crashes due to a `CHECK`-fail. 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.
CWE description: The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
CVSS v3 base score: 5.5
Published: 2021-11-05T20:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/python/summary/writer/writer_test.py
Commit date: 2021-08-31 16:55:31 -0700
Commit message: Merge pull request #51715 from yongtang:46909-tf.summary.create_file_writer

PiperOrigin-RevId: 394109960
Change-Id: I444e59a7f90acd6487832d74b677093403c8a083

Diff: diff --cc tensorflow/python/summary/writer/writer_test.py
index 19138b1372dea,a9f107aa4c247..9fcac4952f6a2
--- a/tensorflow/python/summary/writer/writer_test.py
+++ b/tensorflow/python/summary/writer/writer_test.py
@@@ -683,11 -684,20 +684,21 @@@ class SessionBasedFileWriterTestCase(Fi
      self.assertRaises(StopIteration, lambda: next(events))
  
      # No more files
      self.assertRaises(StopIteration, lambda: next(event_paths))
  
+   def testSummaryFileWritersInvalidInput(self):
+     # Test case for GitHub issue 46909
+     logdir = self.get_temp_dir()
+     with session.Session() as sess:
+       with self.assertRaises(errors_impl.InvalidArgumentError):
+         writer = summary_ops_v2.create_file_writer(
+             logdir=logdir, flush_millis=[1, 2])
+         sess.run(writer.init())
+         sess.run(writer.flush())
+ 
 +
  class FileWriterCacheTest(test.TestCase):
    """FileWriterCache tests."""
  
    def _test_dir(self, test_name):
      """Create an empty dir to use for tests.

Fixed code:    def testSummaryFileWritersInvalidInput(self):
     # Test case for GitHub issue 46909
     logdir = self.get_temp_dir()
     with session.Session() as sess:
       with self.assertRaises(errors_impl.InvalidArgumentError):
         writer = summary_ops_v2.create_file_writer(
             logdir=logdir, flush_millis=[1, 2])
         sess.run(writer.init())
         sess.run(writer.flush())
CVE-2021-41201: Access of Uninitialized Pointer (CWE-824)
value: TensorFlow is an open source platform for machine learning. In affeced versions during execution, `EinsumHelper::ParseEquation()` is supposed to set the flags in `input_has_ellipsis` vector and `*output_has_ellipsis` boolean to indicate whether there is ellipsis in the corresponding inputs and output. However, the code only changes these flags to `true` and never assigns `false`. This results in unitialized variable access if callers assume that `EinsumHelper::ParseEquation()` always sets these flags. 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.
CWE description: The product accesses or uses a pointer that has not been initialized.
CVSS v3 base score: 7.8
Published: 2021-11-05T20:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C
Files changed: tensorflow/core/kernels/linalg/einsum_op_impl.h
Commit date: 2021-08-19 09:10:18 -0700
Commit message: Fix EinsumHelper::ParseEquation to avoid uninitialized accesses.

EinsumHelper::ParseEquation is supposed to return true or false in
input_has_ellipsis and output_has_ellipsis to indicate whether there is
ellipsis in the inputs and output. Previously, when there is no ellipsis in the
inputs or output, the routine doesn't assign false to the variables. This
change initializes the two variables with false to fix the problem.
PiperOrigin-RevId: 391772004
Change-Id: I17b6c88aadef4131470378e48cced054bf252e86

Diff: diff --git a/tensorflow/core/kernels/linalg/einsum_op_impl.h b/tensorflow/core/kernels/linalg/einsum_op_impl.h
index 5c41e38954d62..6f64334555131 100644
--- a/tensorflow/core/kernels/linalg/einsum_op_impl.h
+++ b/tensorflow/core/kernels/linalg/einsum_op_impl.h
@@ -151,18 +151,20 @@ struct EinsumHelper {
     int num_labels = label_mapping.size();
     input_label_counts->resize(num_inputs);
     input_has_ellipsis->resize(num_inputs);
     for (int i = 0; i < num_inputs; ++i) {
       input_label_counts->at(i).resize(num_labels);
+      input_has_ellipsis->at(i) = false;
       for (const int label : input_labels->at(i)) {
         if (label != kEllipsisLabel)
           input_label_counts->at(i)[label] += 1;
         else
           input_has_ellipsis->at(i) = true;
       }
     }
     output_label_counts->resize(num_labels);
+    *output_has_ellipsis = false;
     for (const int label : *output_labels) {
       if (label != kEllipsisLabel)
         output_label_counts->at(label) += 1;
       else
         *output_has_ellipsis = true;

Fixed code:       input_has_ellipsis->at(i) = false;
    *output_has_ellipsis = false;
CVE-2021-41202: Incorrect Conversion between Numeric Types (CWE-681)
value: TensorFlow is an open source platform for machine learning. In affected versions while calculating the size of the output within the `tf.range` kernel, there is a conditional statement of type `int64 = condition ? int64 : double`. Due to C++ implicit conversion rules, both branches of the condition will be cast to `double` and the result would be truncated before the assignment. This result in overflows. 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.
CWE description: When converting from one data type to another, such as long to integer, data can be omitted or translated in a way that produces unexpected values. If the resulting values are used in a sensitive context, then dangerous behaviors may occur.
CVSS v3 base score: 5.5
Published: 2021-11-05T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/kernels/sequence_ops.cc
Commit date: 2021-08-30 13:44:36 -0700
Commit message: Merge pull request #51711 from yongtang:46899-tf.range

PiperOrigin-RevId: 393844345
Change-Id: I2a72193d4416b8b009bc0b21489a42061f164203

Diff: diff --cc tensorflow/core/kernels/sequence_ops.cc
index ad1b1471c3006,ca7fae0d91d4a..bdcf83eb3761f
--- a/tensorflow/core/kernels/sequence_ops.cc
+++ b/tensorflow/core/kernels/sequence_ops.cc
@@@ -76,13 -76,15 +76,14 @@@ class RangeOp : public OpKernel 
        size = static_cast<int64>(
            (std::abs(limit - start) + std::abs(delta) - 1) / std::abs(delta));
      } else {
        size = static_cast<int64>(std::ceil(std::abs((limit - start) / delta)));
      }
+     TensorShape shape;
+     OP_REQUIRES_OK(context, shape.AddDimWithStatus(size));
      Tensor* out = nullptr;
--    OP_REQUIRES_OK(context,
-                    context->allocate_output(0, TensorShape({size}), &out));
 -                   context->allocate_output(0, shape, &out));
++    OP_REQUIRES_OK(context, context->allocate_output(0, shape, &out));
      auto flat = out->flat<T>();
      T val = start;
      for (int64_t i = 0; i < size; ++i) {
        flat(i) = T(val);
        val += delta;

Vulnerable code: -    OP_REQUIRES_OK(context,
                    context->allocate_output(0, TensorShape({size}), &out));
Fixed code:      TensorShape shape;
     OP_REQUIRES_OK(context, shape.AddDimWithStatus(size));
+    OP_REQUIRES_OK(context, context->allocate_output(0, shape, &out));
CVE-2021-41204: Access of Uninitialized Pointer (CWE-824)
value: TensorFlow is an open source platform for machine learning. In affected versions during TensorFlow's Grappler optimizer phase, constant folding might attempt to deep copy a resource tensor. This results in a segfault, as these tensors are supposed to not change. 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.
CWE description: The product accesses or uses a pointer that has not been initialized.
CVSS v3 base score: 5.5
Published: 2021-11-05T21:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/common_runtime/constant_folding.cc
Commit date: 2021-08-19 11:29:55 -0700
Commit message: Don't constant-fold DT_RESOURCE constants.

PiperOrigin-RevId: 391803952
Change-Id: I0ea3ec31d3e7dfda0f03b4027a237f08d00a3091

Diff: diff --git a/tensorflow/core/common_runtime/constant_folding.cc b/tensorflow/core/common_runtime/constant_folding.cc
index 8367e5ff6aff3..ca75dc9f19160 100644
--- a/tensorflow/core/common_runtime/constant_folding.cc
+++ b/tensorflow/core/common_runtime/constant_folding.cc
@@ -28,10 +28,11 @@ limitations under the License.
 #include "tensorflow/core/common_runtime/memory_types.h"
 #include "tensorflow/core/common_runtime/rendezvous_mgr.h"
 #include "tensorflow/core/framework/log_memory.h"
 #include "tensorflow/core/framework/op_kernel.h"
 #include "tensorflow/core/framework/types.h"
+#include "tensorflow/core/framework/types.pb.h"
 #include "tensorflow/core/graph/algorithm.h"
 #include "tensorflow/core/graph/node_builder.h"
 #include "tensorflow/core/graph/subgraph.h"
 #include "tensorflow/core/lib/core/threadpool.h"
 #include "tensorflow/core/lib/gtl/cleanup.h"
@@ -221,11 +222,12 @@ bool IsConstantFoldable(
     const std::function<bool(const Node*)>& consider,
     int64_t max_constant_size_in_bytes,
     std::unordered_map<const Node*, std::vector<Tensor>>*
         shape_replacement_map) {
   if (n->IsConstant()) {
-    return true;
+    // Skip constant folding resources as they cannot be deep copied.
+    return n->output_type(0) != DT_RESOURCE;
   }
   if (MaybeReplaceShapeOp(n, shape_map, shape_replacement_map)) {
     return true;
   }
   if (n->op_def().is_stateful()) {

Vulnerable code:     return true;
Fixed code: #include "tensorflow/core/framework/types.pb.h"
    // Skip constant folding resources as they cannot be deep copied.
    return n->output_type(0) != DT_RESOURCE;
CVE-2021-41211: Out-of-bounds Read (CWE-125)
value: TensorFlow is an open source platform for machine learning. In affected versions the shape inference code for `QuantizeV2` can trigger a read outside of bounds of heap allocated array. This occurs whenever `axis` is a negative value less than `-1`. In this case, we are accessing data before the start of a heap buffer. The code allows `axis` to be an optional argument (`s` would contain an `error::NOT_FOUND` error code). Otherwise, it assumes that `axis` is a valid index into the dimensions of the `input` tensor. If `axis` is less than `-1` then this results in a heap OOB read. The fix will be included in TensorFlow 2.7.0. We will also cherrypick this commit on TensorFlow 2.6.1, as this version is the only one that is also affected.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.1
Published: 2021-11-05T21:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/framework/common_shape_fns.cc
Commit date: 2021-10-01 16:02:45 -0700
Commit message: Prevent OOB access in QuantizeV2 shape inference

PiperOrigin-RevId: 400309614
Change-Id: I31412c71b05b4f21b677f7fa715a61499cbee39d

Diff: diff --git a/tensorflow/core/framework/common_shape_fns.cc b/tensorflow/core/framework/common_shape_fns.cc
index 8c1b3bf1d1c9d..95f2670e0571d 100644
--- a/tensorflow/core/framework/common_shape_fns.cc
+++ b/tensorflow/core/framework/common_shape_fns.cc
@@ -2557,10 +2557,13 @@ Status QuantizeV2Shape(InferenceContext* c) {
   int axis = -1;
   Status s = c->GetAttr("axis", &axis);
   if (!s.ok() && s.code() != error::NOT_FOUND) {
     return s;
   }
+  if (axis < -1) {
+    return errors::InvalidArgument("axis should be at least -1, got ", axis);
+  }
   const int minmax_rank = (axis == -1) ? 0 : 1;
   TF_RETURN_IF_ERROR(shape_inference::UnchangedShape(c));
   ShapeHandle minmax;
   TF_RETURN_IF_ERROR(c->WithRank(c->input(1), minmax_rank, &minmax));
   TF_RETURN_IF_ERROR(c->WithRank(c->input(2), minmax_rank, &minmax));

Fixed code:   if (axis < -1) {
    return errors::InvalidArgument("axis should be at least -1, got ", axis);
  }
CVE-2021-41216: Out-of-bounds Write (CWE-787)
value: TensorFlow is an open source platform for machine learning. In affected versions the shape inference function for `Transpose` is vulnerable to a heap buffer overflow. This occurs whenever `perm` contains negative elements. The shape inference function does not validate that the indices in `perm` are all valid. 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.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2021-11-05T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/ops/array_ops.cc
Commit date: 2021-10-14 19:42:55 -0700
Commit message: Make Transpose's shape inference function validate that negative `perm` values are within the tensor's rank.

PiperOrigin-RevId: 403252853
Change-Id: Ia6b31b45b237312668bb31c2c3b3c7bbce2d2610

Diff: diff --git a/tensorflow/core/ops/array_ops.cc b/tensorflow/core/ops/array_ops.cc
index 64bd4f3847854..14c9efae1ddd3 100644
--- a/tensorflow/core/ops/array_ops.cc
+++ b/tensorflow/core/ops/array_ops.cc
@@ -166,11 +166,11 @@ Status TransposeShapeFn(InferenceContext* c) {
       data = AsInt64<int64_t>(perm, rank);
     }
 
     for (int32_t i = 0; i < rank; ++i) {
       int64_t in_idx = data[i];
-      if (in_idx >= rank) {
+      if (in_idx >= rank || in_idx <= -rank) {
         return errors::InvalidArgument("perm dim ", in_idx,
                                        " is out of range of input rank ", rank);
       }
       dims[i] = c->Dim(input, in_idx);
     }

Vulnerable code:       if (in_idx >= rank) {
Fixed code:       if (in_idx >= rank || in_idx <= -rank) {
CVE-2021-41217: NULL Pointer Dereference (CWE-476)
value: TensorFlow is an open source platform for machine learning. In affected versions the process of building the control flow graph for a TensorFlow model is vulnerable to a null pointer exception when nodes that should be paired are not. This occurs because the code assumes that the first node in the pairing (e.g., an `Enter` node) always exists when encountering the second node (e.g., an `Exit` node). When this is not the case, `parent` is `nullptr` so dereferencing it causes a crash. 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.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 5.5
Published: 2021-11-05T21:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/common_runtime/immutable_executor_state.cc
Commit date: 2021-10-18 16:34:24 -0700
Commit message: Fix a NPE issue in invalid Exit op. Now it will report an error instead of crash.

PiperOrigin-RevId: 404089902
Change-Id: Ia6ec55445ea70ad045a4d339d354959ad0618f2a

Diff: diff --git a/tensorflow/core/common_runtime/immutable_executor_state.cc b/tensorflow/core/common_runtime/immutable_executor_state.cc
index 3f90d027cf436..1f728334e2b7e 100644
--- a/tensorflow/core/common_runtime/immutable_executor_state.cc
+++ b/tensorflow/core/common_runtime/immutable_executor_state.cc
@@ -314,10 +314,14 @@ Status ImmutableExecutorState::BuildControlFlowInfo(const Graph* g,
           GetNodeAttr(curr_node->attrs(), "frame_name", &frame_name));
       parent = curr_node;
     } else if (IsExit(curr_node)) {
       // Exit to the parent frame.
       parent = parent_nodes[curr_id];
+      if (!parent) {
+        return errors::InvalidArgument(
+            "Invalid Exit op: Cannot find a corresponding Enter op.");
+      }
       frame_name = cf_info->frame_names[parent->id()];
       parent = parent_nodes[parent->id()];
     } else {
       parent = parent_nodes[curr_id];
       frame_name = cf_info->frame_names[curr_id];

Fixed code:       if (!parent) {
        return errors::InvalidArgument(
            "Invalid Exit op: Cannot find a corresponding Enter op.");
      }
CVE-2021-41226: Out-of-bounds Read (CWE-125)
value: TensorFlow is an open source platform for machine learning. In affected versions the implementation of `SparseBinCount` is vulnerable to a heap OOB access. This is because of missing validation between the elements of the `values` argument and the shape of the sparse output. 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.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.1
Published: 2021-11-05T21:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/kernels/bincount_op.cc
Commit date: 2021-09-30 06:43:41 -0700
Commit message: Prevent out-of-bound accesses in SparseBincount.

PiperOrigin-RevId: 399918616
Change-Id: I11d154f4444d3fde1f09c5c40628b8671791a30d

Diff: diff --git a/tensorflow/core/kernels/bincount_op.cc b/tensorflow/core/kernels/bincount_op.cc
index 6d668211da096..0f661dd9f201a 100644
--- a/tensorflow/core/kernels/bincount_op.cc
+++ b/tensorflow/core/kernels/bincount_op.cc
@@ -403,10 +403,20 @@ class SparseBincountOp : public OpKernel {
       fill(ctx->eigen_device<Device>(), out_t->flat<T>());
       const auto indices_mat = indices.matrix<int64_t>();
       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);
           } else {
             if (weights_size) {

Fixed code:         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), ")."));
CVE-2022-21726: Out-of-bounds Read (CWE-125)
value: Tensorflow is an Open Source Machine Learning Framework. The implementation of `Dequantize` does not fully validate the value of `axis` and can result in heap OOB accesses. The `axis` argument can be `-1` (the default value for the optional argument) or any other positive value at most the number of dimensions of the input. Unfortunately, the upper bound is not checked and this results in reading past the end of the array containing the dimensions of the input tensor. 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.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 8.8
Published: 2022-02-03T11:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/kernels/dequantize_op.cc
Commit date: 2021-11-19 23:22:12 -0800
Commit message: Fix out of bound access in DequantizeOp by adding check for axis < input dimension

PiperOrigin-RevId: 411214268
Change-Id: I3249d2a69ddc82f182c589a3a5bbfb71543f4b29

Diff: diff --git a/tensorflow/core/kernels/dequantize_op.cc b/tensorflow/core/kernels/dequantize_op.cc
index 31a7a7498cf0c..0a466f1cf118e 100644
--- a/tensorflow/core/kernels/dequantize_op.cc
+++ b/tensorflow/core/kernels/dequantize_op.cc
@@ -92,10 +92,15 @@ class DequantizeOp : public OpKernel {
   void Compute(OpKernelContext* ctx) override {
     const Tensor& input = ctx->input(0);
     const Tensor& input_min_tensor = ctx->input(1);
     const Tensor& input_max_tensor = ctx->input(2);
 
+    OP_REQUIRES(
+        ctx, axis_ < input.dims(),
+        errors::InvalidArgument("Axis must be less than input dimension(",
+                                input.dims(), "), got ", axis_));
+
     int num_slices = 1;
     if (axis_ > -1) {
       num_slices = input.dim_size(axis_);
     }
     OP_REQUIRES(ctx, input_min_tensor.NumElements() == num_slices,

Fixed code:     OP_REQUIRES(
        ctx, axis_ < input.dims(),
        errors::InvalidArgument("Axis must be less than input dimension(",
                                input.dims(), "), got ", axis_));
CVE-2022-21728: Out-of-bounds Read (CWE-125)
value: Tensorflow is an Open Source Machine Learning Framework. The implementation of shape inference for `ReverseSequence` does not fully validate the value of `batch_dim` and can result in a heap OOB read. There is a check to make sure the value of `batch_dim` does not go over the rank of the input, but there is no check for negative values. Negative dimensions are allowed in some cases to mimic Python's negative indexing (i.e., indexing from the end of the array), however if the value is too negative then the implementation of `Dim` would access elements before the start of an array. 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.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 8.1
Published: 2022-02-03T11:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/ops/array_ops.cc
Commit date: 2021-11-23 14:42:02 -0800
Commit message: Fix out of bound error in ReverseSequence Op shape function

PiperOrigin-RevId: 411896080
Change-Id: I7e59a38e2f960886edf2b6c54ed5a84e86a9b193

Diff: diff --git a/tensorflow/core/ops/array_ops.cc b/tensorflow/core/ops/array_ops.cc
index bcdc6643c89ad..1a88b16b865dd 100644
--- a/tensorflow/core/ops/array_ops.cc
+++ b/tensorflow/core/ops/array_ops.cc
@@ -1651,15 +1651,25 @@ REGISTER_OP("ReverseSequence")
       const int32_t input_rank = c->Rank(input);
       if (batch_dim >= input_rank) {
         return errors::InvalidArgument(
             "batch_dim must be < input rank: ", batch_dim, " vs. ", input_rank);
       }
+
       if (seq_dim >= input_rank) {
         return errors::InvalidArgument(
             "seq_dim must be < input rank: ", seq_dim, " vs. ", input_rank);
       }
 
+      // To prevent out of bound access when calling c->Dim(input, batch_dim),
+      // batch_dim range [-1 * input rank, input rank) is allowed. However,
+      // the op implementation has a stricter bound for batch_dim requiring >= 0
+      // value. Thus, perform strict check here.
+      if (batch_dim < 0) {
+        return errors::InvalidArgument("batch_dim must be >=0, got ",
+                                       batch_dim);
+      }
+
       DimensionHandle batch_dim_dim = c->Dim(input, batch_dim);
       TF_RETURN_IF_ERROR(
           c->Merge(batch_dim_dim, c->Dim(seq_lens_shape, 0), &batch_dim_dim));
 
       // Replace batch_dim of input with batch_size

Fixed code: 
      // To prevent out of bound access when calling c->Dim(input, batch_dim),
      // batch_dim range [-1 * input rank, input rank) is allowed. However,
      // the op implementation has a stricter bound for batch_dim requiring >= 0
      // value. Thus, perform strict check here.
      if (batch_dim < 0) {
        return errors::InvalidArgument("batch_dim must be >=0, got ",
                                       batch_dim);
      }
CVE-2022-21741: Divide By Zero (CWE-369)
value: Tensorflow is an Open Source Machine Learning Framework. ### Impact An attacker can craft a TFLite model that would trigger a division by zero in the implementation of depthwise convolutions. The parameters of the convolution can be user controlled and are also used within a division operation to determine the size of the padding that needs to be added before applying the convolution. There is no check before this division that the divisor is strictly positive. 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.
CWE description: The product divides a value by zero.
CVSS v3 base score: 6.5
Published: 2022-02-03T15:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/lite/kernels/depthwise_conv.cc
Commit date: 2021-12-14 17:13:47 -0800
Commit message: [lite] Add validation check for dilation height/width to be positive integers.

PiperOrigin-RevId: 416429178
Change-Id: If7cdcddca54486434d9b2f06e7e2b401d7c3ee25

Diff: diff --git a/tensorflow/lite/kernels/depthwise_conv.cc b/tensorflow/lite/kernels/depthwise_conv.cc
index 060b0827dafa7..e1a54adcc7fd0 100644
--- a/tensorflow/lite/kernels/depthwise_conv.cc
+++ b/tensorflow/lite/kernels/depthwise_conv.cc
@@ -113,10 +113,12 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
   TF_LITE_ENSURE_OK(context,
                     GetOutputSafe(context, node, kOutputTensor, &output));
 
   TF_LITE_ENSURE_EQ(context, NumDimensions(input), 4);
   TF_LITE_ENSURE_EQ(context, NumDimensions(filter), 4);
+  TF_LITE_ENSURE(context, params->dilation_height_factor > 0);
+  TF_LITE_ENSURE(context, params->dilation_width_factor > 0);
 
   const TfLiteType data_type = input->type;
 
   const TfLiteType filter_type = filter->type;
   const bool is_hybrid =

Fixed code:   TF_LITE_ENSURE(context, params->dilation_height_factor > 0);
  TF_LITE_ENSURE(context, params->dilation_width_factor > 0);
CVE-2022-23557: Divide By Zero (CWE-369)
value: Tensorflow is an Open Source Machine Learning Framework. An attacker can craft a TFLite model that would trigger a division by zero in `BiasAndClamp` implementation. There is no check that the `bias_size` is non zero. 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.
CWE description: The product divides a value by zero.
CVSS v3 base score: 6.5
Published: 2022-02-04T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C
Files changed: tensorflow/lite/kernels/internal/common.h
Commit date: 2021-12-14 13:45:48 -0800
Commit message: [lite] Add check for bias_size is zero to avoid division by zero. This shouldn't happen for properly converted models. Just safety check

PiperOrigin-RevId: 416383645
Change-Id: If8e508bf696ae8ecfb927e69c139a8ccf7fe60cb

Diff: diff --git a/tensorflow/lite/kernels/internal/common.h b/tensorflow/lite/kernels/internal/common.h
index 38fa9167fd9da..5e8778f183ec3 100644
--- a/tensorflow/lite/kernels/internal/common.h
+++ b/tensorflow/lite/kernels/internal/common.h
@@ -73,10 +73,11 @@ float ActivationFunction(float x) {
 }
 
 inline void BiasAndClamp(float clamp_min, float clamp_max, int bias_size,
                          const float* bias_data, int array_size,
                          float* array_data) {
+  if (bias_size == 0) return;
   // Note: see b/132215220: in May 2019 we thought it would be OK to replace
   // this with the Eigen one-liner:
   //   return (array.colwise() + bias).cwiseMin(clamp_max).cwiseMin(clamp_max).
   // This turned out to severely regress performance: +4ms (i.e. 8%) on
   // MobileNet v2 / 1.0 / 224. So we keep custom NEON code for now.

Fixed code:   if (bias_size == 0) return;
CVE-2022-23565: Reachable Assertion (CWE-617)
value: Tensorflow is an Open Source Machine Learning Framework. An attacker can trigger denial of service via assertion failure by altering a `SavedModel` on disk such that `AttrDef`s of some operation are duplicated. 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.
CWE description: The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
CVSS v3 base score: 6.5
Published: 2022-02-04T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/framework/op_def_util.cc
Commit date: 2021-11-08 10:21:15 -0800
Commit message: Remove a `DCHECK`-fail, log an error instead.

`DCHECK` in debug mode results in crashes. TensorFlow has had multiple vulnerabilities due to this.

Outside of debug mode, `DCHECK` is a no-op.

A better alternative is to report an error to the log buffer and continue. This should happen both in debug mode and in prod mode.

PiperOrigin-RevId: 408375925
Change-Id: Id5b3e19c73f3fbe0cc4bba26ca44ff9607bb6356

Diff: diff --git a/tensorflow/core/framework/op_def_util.cc b/tensorflow/core/framework/op_def_util.cc
index dcbe5f38ce88e..6127913d9ba1f 100644
--- a/tensorflow/core/framework/op_def_util.cc
+++ b/tensorflow/core/framework/op_def_util.cc
@@ -819,13 +819,14 @@ uint64 AttrDefHash(const OpDef::AttrDef& a) {
 bool RepeatedAttrDefEqual(
     const protobuf::RepeatedPtrField<OpDef::AttrDef>& a1,
     const protobuf::RepeatedPtrField<OpDef::AttrDef>& a2) {
   std::unordered_map<string, const OpDef::AttrDef*> a1_set;
   for (const OpDef::AttrDef& def : a1) {
-    DCHECK(a1_set.find(def.name()) == a1_set.end())
-        << "AttrDef names must be unique, but '" << def.name()
-        << "' appears more than once";
+    if (a1_set.find(def.name()) != a1_set.end()) {
+      LOG(ERROR) << "AttrDef names must be unique, but '" << def.name()
+                 << "' appears more than once";
+    }
     a1_set[def.name()] = &def;
   }
   for (const OpDef::AttrDef& def : a2) {
     auto iter = a1_set.find(def.name());
     if (iter == a1_set.end()) return false;

Vulnerable code:     DCHECK(a1_set.find(def.name()) == a1_set.end())
        << "AttrDef names must be unique, but '" << def.name()
        << "' appears more than once";
Fixed code:     if (a1_set.find(def.name()) != a1_set.end()) {
      LOG(ERROR) << "AttrDef names must be unique, but '" << def.name()
                 << "' appears more than once";
    }
CVE-2022-23566: Out-of-bounds Write (CWE-787)
value: Tensorflow is an Open Source Machine Learning Framework. TensorFlow is vulnerable to a heap OOB write in `Grappler`. The `set_output` function writes to an array at the specified index. Hence, this gives a malicious user a write primitive. 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.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 8.8
Published: 2022-02-04T23:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/grappler/costs/graph_properties.cc
Commit date: 2021-11-08 05:54:06 -0800
Commit message: Prevent a crash due to heap OOB write in grappler.

PiperOrigin-RevId: 408318417
Change-Id: If095feb8c001e3a8ac4a85b7387b81e8309df47d

Diff: diff --git a/tensorflow/core/grappler/costs/graph_properties.cc b/tensorflow/core/grappler/costs/graph_properties.cc
index 51a2cd080c544..3cc12173ba10c 100644
--- a/tensorflow/core/grappler/costs/graph_properties.cc
+++ b/tensorflow/core/grappler/costs/graph_properties.cc
@@ -1132,11 +1132,16 @@ class SymbolicShapeRefiner {
   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");
+      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();
   }
 

Vulnerable code:       return errors::InvalidArgument("Missing context");
Fixed code:       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);
CVE-2022-23567: Integer Overflow or Wraparound (CWE-190)
value: Tensorflow is an Open Source Machine Learning Framework. The implementations of `Sparse*Cwise*` ops are vulnerable to integer overflows. These can be used to trigger large allocations (so, OOM based denial of service) or `CHECK`-fails when building new `TensorShape` objects (so, assert failures based denial of service). We are missing some validation on the shapes of the input tensors as well as directly constructing a large `TensorShape` with user-provided dimensions. 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.
CWE description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
CVSS v3 base score: 6.5
Published: 2022-02-03T12:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: C++
Files changed: tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
Commit date: 2021-12-10 10:05:21 -0800
Commit message: Prevent overflow in sparse dense cwise ops.

PiperOrigin-RevId: 415543171
Change-Id: I22dab7c41be2121ab5efe5403ca0e2f9b7cb24b8

Diff: diff --git a/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc b/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
index db27abfda7e53..29534bf0a2625 100644
--- a/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
+++ b/tensorflow/core/kernels/sparse_dense_binary_op_shared.cc
@@ -97,11 +97,13 @@ class SparseDenseBinaryOpShared : public OpKernel {
                 errors::InvalidArgument(
                     "The shape argument requires at least one element."));
 
     const auto indices_mat = indices_t->matrix<int64_t>();
     const auto shape_vec = shape_t->vec<int64_t>();
-    const auto lhs_dims = BCast::FromShape(TensorShape(shape_vec));
+    TensorShape lhs_shape;
+    OP_REQUIRES_OK(ctx, TensorShape::BuildTensorShape(shape_vec, &lhs_shape));
+    const auto lhs_dims = BCast::FromShape(lhs_shape);
     const auto rhs_dims = BCast::FromShape(dense_t->shape());
     BCast b(lhs_dims, rhs_dims, false);  // false for keeping the same num dims.
 
     // True iff (size(lhs) >= size(rhs)) and all dims in lhs is greater or equal
     // to dims in rhs (from right to left).

Vulnerable code:     const auto lhs_dims = BCast::FromShape(TensorShape(shape_vec));
Fixed code:     TensorShape lhs_shape;
    OP_REQUIRES_OK(ctx, TensorShape::BuildTensorShape(shape_vec, &lhs_shape));
    const auto lhs_dims = BCast::FromShape(lhs_shape);