CVE-2022-41891: Other (NVD-CWE-Other)
value: TensorFlow is an open source platform for machine learning. If `tf.raw_ops.TensorListConcat` is given `element_shape=[]`, it results segmentation fault which can be used to trigger a denial of service attack. We have patched the issue in GitHub commit fc33f3dc4c14051a83eec6535b608abe1d355fde. The fix will be included in TensorFlow 2.11. We will also cherrypick this commit on TensorFlow 2.10.1, 2.9.3, and TensorFlow 2.8.4, as these are also affected and still in supported range.
CWE description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
CVSS v3 base score: 7.5
Published: 2022-11-18T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/list_kernels.h, tensorflow/python/kernel_tests/data_structures/list_ops_test.py
Commit date: 2022-09-28 13:58:21 -0700
Commit message: Fix tf.raw_ops.TensorListConcat vulnerability (segfault).

Check that the element_shape input is valid.
Add graph/eager unit tests.

Note: This fix will have to be cherry picked in r2.10, r2.9, and r2.8.
PiperOrigin-RevId: 477544091

Diff: diff --git a/tensorflow/core/kernels/list_kernels.h b/tensorflow/core/kernels/list_kernels.h
index 9a0782b830ce4..19fb3d48bc7b9 100644
--- a/tensorflow/core/kernels/list_kernels.h
+++ b/tensorflow/core/kernels/list_kernels.h
@@ -393,12 +393,15 @@ class TensorListConcat : public OpKernel {
   }
 
   void Compute(OpKernelContext* c) override {
     PartialTensorShape element_shape_except_first_dim;
     if (!element_shape_.unknown_rank()) {
-      element_shape_except_first_dim = PartialTensorShape(
-          gtl::ArraySlice<int64_t>(element_shape_.dim_sizes()).subspan(1));
+      auto dim_sizes = element_shape_.dim_sizes();
+      OP_REQUIRES(c, !dim_sizes.empty(),
+                  errors::InvalidArgument("element_shape must not be empty"));
+      element_shape_except_first_dim =
+          PartialTensorShape(gtl::ArraySlice<int64_t>(dim_sizes).subspan(1));
     }
     // Check that the input Variant tensor is indeed a TensorList and has the
     // correct element type.
     const TensorList* tensor_list = nullptr;
     OP_REQUIRES_OK(c, GetInputList(c, 0, &tensor_list));
diff --git a/tensorflow/python/kernel_tests/data_structures/list_ops_test.py b/tensorflow/python/kernel_tests/data_structures/list_ops_test.py
index b966b31300ce7..c95c27eadc0fb 100644
--- a/tensorflow/python/kernel_tests/data_structures/list_ops_test.py
+++ b/tensorflow/python/kernel_tests/data_structures/list_ops_test.py
@@ -1512,10 +1512,19 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase):
         r"List contains uninitialized tensor at index 0"
         r" but leading_dims has only 0 elements."):
       t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32)
       self.evaluate(t)
 
+  @test_util.run_in_graph_and_eager_modes
+  def testConcatWithInvalidElementShape(self):
+    l = list_ops.tensor_list_reserve(
+        element_dtype=dtypes.float32, element_shape=[], num_elements=0)
+    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
+                                r"element_shape must not be empty"):
+      self.evaluate(gen_list_ops.tensor_list_concat(
+          input_handle=l, element_dtype=dtypes.float32, element_shape=[]))
+
   def testEmptyTensorListInvalidShape(self):
     with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                 r"Shape must be at most rank 1 but is rank 2"):
       t = gen_list_ops.EmptyTensorList(
           element_shape=array_ops.ones(dtype=dtypes.int32, shape=[1, 0]),

Vulnerable code:       element_shape_except_first_dim = PartialTensorShape(
          gtl::ArraySlice<int64_t>(element_shape_.dim_sizes()).subspan(1));
Fixed code:       auto dim_sizes = element_shape_.dim_sizes();
      OP_REQUIRES(c, !dim_sizes.empty(),
                  errors::InvalidArgument("element_shape must not be empty"));
      element_shape_except_first_dim =
          PartialTensorShape(gtl::ArraySlice<int64_t>(dim_sizes).subspan(1));
  @test_util.run_in_graph_and_eager_modes
  def testConcatWithInvalidElementShape(self):
    l = list_ops.tensor_list_reserve(
        element_dtype=dtypes.float32, element_shape=[], num_elements=0)
    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                r"element_shape must not be empty"):
      self.evaluate(gen_list_ops.tensor_list_concat(
          input_handle=l, element_dtype=dtypes.float32, element_shape=[]))