CVE-2023-25665 (Python, published 2023-03-25T00:15Z)
Description: value: TensorFlow is an open source platform for machine learning. Prior to versions 2.12.0 and 2.11.1, when `SparseSparseMaximum` is given invalid sparse tensors as inputs, it can give a null pointer error. A fix is included in TensorFlow version 2.12 and version 2.11.1.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-476 \u2014 NULL Pointer Dereference
The product dereferences a pointer that it expects to be valid but is NULL.
Repository: https://github.com/tensorflow/tensorflow
Files changed:
tensorflow/core/kernels/sparse_sparse_binary_op_shared.cc
tensorflow/python/kernel_tests/sparse_ops/sparse_ops_test.py
Commit message: Add validation checks in sparse binary ops.

Fixes a nullptr security vulnerability.

PiperOrigin-RevId: 503501621


Vulnerable code:
    OP_REQUIRES(
        ctx,
        TensorShapeUtils::IsMatrix(a_indices_t->shape()) &&
            TensorShapeUtils::IsMatrix(b_indices_t->shape()),
        errors::InvalidArgument("Inputs a_indices and b_indices should be "
                                "matrices but received shapes: ",
                                a_indices_t->shape().DebugString(), ", ",
                                b_indices_t->shape().DebugString()));
    OP_REQUIRES(ctx,
                TensorShapeUtils::IsVector(a_values_t->shape()) &&
                    TensorShapeUtils::IsVector(b_values_t->shape()),
                errors::InvalidArgument(
                    "Inputs a_values and b_values should be vectors "
                    "but received shapes: ",
                    a_values_t->shape().DebugString(), " and ",
                    b_values_t->shape().DebugString()));
    OP_REQUIRES(
        ctx, a_values.size() == a_nnz && b_values.size() == b_nnz,
        errors::InvalidArgument("Expected ", a_nnz, " and ", b_nnz,
                                " non-empty input values, got ",
                                a_values.size(), " and ", b_values.size()));

    OP_REQUIRES(ctx,
                TensorShapeUtils::IsVector(a_shape_t->shape()) &&
                    TensorShapeUtils::IsVector(b_shape_t->shape()),
                errors::InvalidArgument(
                    "Input shapes should be a vector but received shapes ",
                    a_shape_t->shape().DebugString(), " and ",
                    b_shape_t->shape().DebugString()));
    OP_REQUIRES(
        ctx, a_shape_t->NumElements() == num_dims,
        errors::InvalidArgument("Second dimension of a_indices and length of "
                                "a_shape must match, got ",
                                num_dims, " and ", a_shape_t->NumElements()));
    std::vector<std::pair<bool, int64>> entries_to_copy;  // from_a?, idx

Fixed code:
#include "tensorflow/core/kernels/sparse_utils.h"
    OP_REQUIRES_OK(ctx, sparse_utils::ValidateSparseTensor<int64_t>(
                            *a_indices_t, *a_values_t, *a_shape_t,
                            sparse_utils::IndexValidation::kUnordered));
    OP_REQUIRES_OK(ctx, sparse_utils::ValidateSparseTensor<int64_t>(
                            *b_indices_t, *b_values_t, *b_shape_t,
                            sparse_utils::IndexValidation::kUnordered));
    std::vector<std::pair<bool, int64_t>> entries_to_copy;  // from_a?, idx
from tensorflow.python.ops import gen_sparse_ops
  def testInvalidSparseInputs(self):
    with test_util.force_cpu():
      with self.assertRaisesRegex(
          (ValueError, errors.InvalidArgumentError),
          ".*Index rank .* and shape rank .* do not match.*",
      ):
        self.evaluate(
            gen_sparse_ops.sparse_sparse_maximum(
                [[1]], [0], [2], [[]], [1], [2]
            )
        )