CVE-2022-41901: Reachable Assertion (CWE-617)
value: TensorFlow is an open source platform for machine learning. An input `sparse_matrix` that is not a matrix with a shape with rank 0 will trigger a `CHECK` fail in `tf.raw_ops.SparseMatrixNNZ`. We have patched the issue in GitHub commit f856d02e5322821aad155dad9b3acab1e9f5d693. 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: 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: 7.5
Published: 2022-11-18T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/sparse/sparse_matrix.h, tensorflow/python/kernel_tests/linalg/sparse/csr_sparse_matrix_ops_test.py
Commit date: 2022-09-23 08:44:41 -0700
Commit message: Fix missing sparse matrix crash.

Calling a sparse matrix op with no matrix currently causes a crash.  Here we check and
return a non-ok status.

PiperOrigin-RevId: 476379116

Diff: diff --git a/tensorflow/core/kernels/sparse/sparse_matrix.h b/tensorflow/core/kernels/sparse/sparse_matrix.h
index b2ec20acc6584..15fbe5df6ebe2 100644
--- a/tensorflow/core/kernels/sparse/sparse_matrix.h
+++ b/tensorflow/core/kernels/sparse/sparse_matrix.h
@@ -23,14 +23,16 @@ limitations under the License.
 #endif
 
 #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
 #include "tensorflow/core/framework/op_kernel.h"
 #include "tensorflow/core/framework/tensor.h"
+#include "tensorflow/core/framework/tensor_shape.h"
 #include "tensorflow/core/framework/tensor_types.h"
 #include "tensorflow/core/framework/variant.h"
 #include "tensorflow/core/framework/variant_encode_decode.h"
 #include "tensorflow/core/framework/variant_op_registry.h"
+#include "tensorflow/core/platform/errors.h"
 
 namespace tensorflow {
 
 class CSRSparseMatrix {
   // CreateCSRSparseMatrix is the main method used to construct a
@@ -631,10 +633,15 @@ struct CSRComponent {
 
 template <typename T>
 Status ExtractVariantFromInput(OpKernelContext* ctx, int index,
                                const T** value) {
   const Tensor& input_t = ctx->input(index);
+  if (!TensorShapeUtils::IsScalar(input_t.shape())) {
+    return errors::InvalidArgument(
+        "Invalid input matrix: Shape must be rank 0 but is rank ",
+        input_t.dims());
+  }
   const Variant& input_variant = input_t.scalar<Variant>()();
   *value = input_variant.get<T>();
   if (*value == nullptr) {
     return errors::InvalidArgument("Could not retrieve Variant input ", index);
   }
diff --git a/tensorflow/python/kernel_tests/linalg/sparse/csr_sparse_matrix_ops_test.py b/tensorflow/python/kernel_tests/linalg/sparse/csr_sparse_matrix_ops_test.py
index 035791ce0a5bf..d129bea768e85 100644
--- a/tensorflow/python/kernel_tests/linalg/sparse/csr_sparse_matrix_ops_test.py
+++ b/tensorflow/python/kernel_tests/linalg/sparse/csr_sparse_matrix_ops_test.py
@@ -1311,10 +1311,20 @@ class CSRSparseMatrixOpsTest(test.TestCase):
       # Check that cholesky with AMD ordering has a strictly lower nonzero count
       # for this matrix.
       self.assertLess(cholesky_with_amd_nnz_value,
                       cholesky_without_ordering_nnz_value)
 
+  @test_util.run_in_graph_and_eager_modes
+  def testNoMatrixNoCrash(self):
+    # Round-about way of creating an empty variant tensor that works in both
+    # graph and eager modes.
+    no_matrix = array_ops.reshape(dense_to_csr_sparse_matrix([[0.0]]), [1])[0:0]
+    with self.assertRaisesRegex(
+        (ValueError, errors.InvalidArgumentError),
+        "(Invalid input matrix)|(Shape must be rank 0)"):
+      sparse_csr_matrix_ops.sparse_matrix_nnz(no_matrix)
+
 
 class CSRSparseMatrixOpsBenchmark(test.Benchmark):
 
   def benchmark_sparse_matrix_mat_mul_gpu(self):
     if not test_util.is_gpu_available():

Fixed code: #include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/platform/errors.h"
  if (!TensorShapeUtils::IsScalar(input_t.shape())) {
    return errors::InvalidArgument(
        "Invalid input matrix: Shape must be rank 0 but is rank ",
        input_t.dims());
  }
  @test_util.run_in_graph_and_eager_modes
  def testNoMatrixNoCrash(self):
    # Round-about way of creating an empty variant tensor that works in both
    # graph and eager modes.
    no_matrix = array_ops.reshape(dense_to_csr_sparse_matrix([[0.0]]), [1])[0:0]
    with self.assertRaisesRegex(
        (ValueError, errors.InvalidArgumentError),
        "(Invalid input matrix)|(Shape must be rank 0)"):
      sparse_csr_matrix_ops.sparse_matrix_nnz(no_matrix)