CVE-2023-25663: NULL Pointer Dereference (CWE-476)
value: TensorFlow is an open source platform for machine learning. Prior to versions 2.12.0 and 2.11.1, when `ctx->step_containter()` is a null ptr, the Lookup function will be executed with a null pointer. A fix is included in TensorFlow 2.12.0 and 2.11.1.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 7.5
Published: 2023-03-25T00:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/tensor_array_ops.cc, tensorflow/python/kernel_tests/data_structures/tensor_array_ops_test.py
Commit date: 2023-01-24 11:39:25 -0800
Commit message: Fixing null pointer read in TensorArrayConcat when the step container is missing.

PiperOrigin-RevId: 504332194

Diff: diff --git a/tensorflow/core/kernels/tensor_array_ops.cc b/tensorflow/core/kernels/tensor_array_ops.cc
index 223478affe8c3..bd23fceb6a541 100644
--- a/tensorflow/core/kernels/tensor_array_ops.cc
+++ b/tensorflow/core/kernels/tensor_array_ops.cc
@@ -78,12 +78,13 @@ Status GetTensorArray(OpKernelContext* ctx, TensorArray** tensor_array) {
   string ta_handle;
   if (ctx->input_dtype(0) != DT_RESOURCE) {
     TF_RETURN_IF_ERROR(GetHandle(ctx, &container, &ta_handle));
     ResourceMgr* rm = ctx->resource_manager();
     if (rm == nullptr) return errors::Internal("No resource manager.");
-    TF_RETURN_IF_ERROR(
-        ctx->step_container()->Lookup(rm, container + ta_handle, tensor_array));
+    ScopedStepContainer* sc = ctx->step_container();
+    if (sc == nullptr) return errors::Internal("No step container.");
+    TF_RETURN_IF_ERROR(sc->Lookup(rm, container + ta_handle, tensor_array));
     return OkStatus();
   } else {
     return LookupResource(ctx, HandleFromInput(ctx, 0), tensor_array);
   }
 }
diff --git a/tensorflow/python/kernel_tests/data_structures/tensor_array_ops_test.py b/tensorflow/python/kernel_tests/data_structures/tensor_array_ops_test.py
index f5c310e1fd03a..ea82744fede4d 100644
--- a/tensorflow/python/kernel_tests/data_structures/tensor_array_ops_test.py
+++ b/tensorflow/python/kernel_tests/data_structures/tensor_array_ops_test.py
@@ -1844,10 +1844,26 @@ class TensorArrayTest(test.TestCase):
   def testStackShapeOnStaticSize(self):
     ta = tensor_array_ops.TensorArray(dtypes.float32, size=42)
     ta = ta.write(0, [0])
     self.assertEqual([42, 1], ta.stack().shape.as_list())
 
+  def testTensorArrayConcatFailsWhenMissingStepContainer(self):
+    @def_function.function
+    def func():
+      y = data_flow_ops.TensorArrayConcatV2(
+          handle=["a", "b"],
+          flow_in=0.1,
+          dtype=dtypes.int32,
+          element_shape_except0=1,
+      )
+      return y
+
+    with self.assertRaisesRegex(
+        errors.NotFoundError, "Container .* does not exist"
+    ):
+      self.evaluate(func())
+
 
 class TensorArrayBenchmark(test.Benchmark):
 
   def _tensorArrayWriteInWhile(self):
     size = 10000

Vulnerable code:     TF_RETURN_IF_ERROR(
        ctx->step_container()->Lookup(rm, container + ta_handle, tensor_array));
Fixed code:     ScopedStepContainer* sc = ctx->step_container();
    if (sc == nullptr) return errors::Internal("No step container.");
    TF_RETURN_IF_ERROR(sc->Lookup(rm, container + ta_handle, tensor_array));
  def testTensorArrayConcatFailsWhenMissingStepContainer(self):
    @def_function.function
    def func():
      y = data_flow_ops.TensorArrayConcatV2(
          handle=["a", "b"],
          flow_in=0.1,
          dtype=dtypes.int32,
          element_shape_except0=1,
      )
      return y

    with self.assertRaisesRegex(
        errors.NotFoundError, "Container .* does not exist"
    ):
      self.evaluate(func())