VYPR
Low severityNVD Advisory· Published May 14, 2021· Updated Aug 3, 2024

CHECK-fail in SparseCross due to type confusion

CVE-2021-29519

Description

TensorFlow is an end-to-end open source platform for machine learning. The API of tf.raw_ops.SparseCross allows combinations which would result in a CHECK-failure and denial of service. This is because the implementation(https://github.com/tensorflow/tensorflow/blob/3d782b7d47b1bf2ed32bd4a246d6d6cadc4c903d/tensorflow/core/kernels/sparse_cross_op.cc#L114-L116) is tricked to consider a tensor of type tstring which in fact contains integral elements. Fixing the type confusion by preventing mixing DT_STRING and DT_INT64 types solves this issue. The fix will be included in TensorFlow 2.5.0. We will also cherrypick this commit on TensorFlow 2.4.2, TensorFlow 2.3.3, TensorFlow 2.2.3 and TensorFlow 2.1.4, as these are also affected and still in supported range.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
tensorflowPyPI
< 2.1.42.1.4
tensorflowPyPI
>= 2.2.0, < 2.2.32.2.3
tensorflowPyPI
>= 2.3.0, < 2.3.32.3.3
tensorflowPyPI
>= 2.4.0, < 2.4.22.4.2
tensorflow-cpuPyPI
< 2.1.42.1.4
tensorflow-cpuPyPI
>= 2.2.0, < 2.2.32.2.3
tensorflow-cpuPyPI
>= 2.3.0, < 2.3.32.3.3
tensorflow-cpuPyPI
>= 2.4.0, < 2.4.22.4.2
tensorflow-gpuPyPI
< 2.1.42.1.4
tensorflow-gpuPyPI
>= 2.2.0, < 2.2.32.2.3
tensorflow-gpuPyPI
>= 2.3.0, < 2.3.32.3.3
tensorflow-gpuPyPI
>= 2.4.0, < 2.4.22.4.2

Affected products

1

Patches

1
b1cc5e5a50e7

Fix `tf.raw_ops.SparseCross` failing CHECK.

https://github.com/tensorflow/tensorflowAmit PatankarApr 15, 2021via ghsa
1 file changed · +48 7
  • tensorflow/core/kernels/sparse_cross_op.cc+48 7 modified
    @@ -27,6 +27,7 @@ limitations under the License.
     #include "tensorflow/core/framework/tensor.h"
     #include "tensorflow/core/framework/tensor_shape.h"
     #include "tensorflow/core/framework/types.h"
    +#include "tensorflow/core/framework/types.pb.h"
     #include "tensorflow/core/lib/core/stringpiece.h"
     #include "tensorflow/core/lib/strings/str_util.h"
     #include "tensorflow/core/platform/fingerprint.h"
    @@ -460,10 +461,19 @@ int64 CalculateBatchSize(const OpInputList& shapes_list_in,
     Status ValidateInput(const OpInputList& indices_list_in,
                          const OpInputList& values_list_in,
                          const OpInputList& shapes_list_in,
    -                     const OpInputList& dense_list_in) {
    +                     const OpInputList& dense_list_in,
    +                     const DataType& internal_type) {
       const auto size = indices_list_in.size();
    +  // Only perform internal_type check for SparseCrossOp.
    +  // Check if the internal_type is not invalid before doing so.
    +  bool check_type = internal_type != DT_INVALID;
       // Validates indices_list_in OpInputList.
       for (int i = 0; i < size; i++) {
    +    if (check_type && indices_list_in[i].dtype() != DT_INT64) {
    +      return errors::InvalidArgument("Input indices should be of type ",
    +                                     DT_INT64, " but received ",
    +                                     indices_list_in[i].dtype());
    +    }
         if (!TensorShapeUtils::IsMatrix(indices_list_in[i].shape())) {
           return errors::InvalidArgument(
               "Input indices should be a matrix but received shape ",
    @@ -482,6 +492,14 @@ Status ValidateInput(const OpInputList& indices_list_in,
                                        values_list_in.size());
       }
       for (int i = 0; i < size; i++) {
    +    // Make sure to avoid the expected type to be string, but input values to be
    +    // int64.
    +    if (check_type && internal_type == DT_STRING &&
    +        values_list_in[i].dtype() == DT_INT64) {
    +      return errors::InvalidArgument("Input values should be of internal type ",
    +                                     internal_type, " but received ",
    +                                     values_list_in[i].dtype());
    +    }
         if (!TensorShapeUtils::IsVector(values_list_in[i].shape())) {
           return errors::InvalidArgument(
               "Input values should be a vector but received shape ",
    @@ -502,6 +520,11 @@ Status ValidateInput(const OpInputList& indices_list_in,
                                        shapes_list_in.size());
       }
       for (int i = 0; i < size; i++) {
    +    if (check_type && shapes_list_in[i].dtype() != DT_INT64) {
    +      return errors::InvalidArgument("Input shape should be of type ", DT_INT64,
    +                                     " but received ",
    +                                     shapes_list_in[i].dtype());
    +    }
         if (!TensorShapeUtils::IsVector(shapes_list_in[i].shape())) {
           return errors::InvalidArgument(
               "Input shapes should be a vector but received shape ",
    @@ -517,6 +540,14 @@ Status ValidateInput(const OpInputList& indices_list_in,
     
       // Validates dense_list_in OpInputList
       for (int i = 0; i < dense_list_in.size(); ++i) {
    +    // Make sure to avoid the expected type to be string, but input values to be
    +    // int64.
    +    if (check_type && internal_type == DT_STRING &&
    +        dense_list_in[i].dtype() == DT_INT64) {
    +      return errors::InvalidArgument("Dense inputs should be of internal type ",
    +                                     internal_type, " but received ",
    +                                     dense_list_in[i].dtype());
    +    }
         if (!TensorShapeUtils::IsMatrix(dense_list_in[i].shape())) {
           return errors::InvalidArgument(
               "Dense inputs should be a matrix but received shape ",
    @@ -698,6 +729,7 @@ class SparseCrossOp : public OpKernel {
         int64 signed_hash_key_;
         OP_REQUIRES_OK(context, context->GetAttr("hash_key", &signed_hash_key_));
         hash_key_ = static_cast<uint64>(signed_hash_key_);
    +    OP_REQUIRES_OK(context, context->GetAttr("internal_type", &internal_type_));
       }
     
       void Compute(OpKernelContext* context) override {
    @@ -711,8 +743,10 @@ class SparseCrossOp : public OpKernel {
         OP_REQUIRES_OK(context,
                        context->input_list("dense_inputs", &dense_list_in));
     
    -    OP_REQUIRES_OK(context, ValidateInput(indices_list_in, values_list_in,
    -                                          shapes_list_in, dense_list_in));
    +    DataType internal_type = internal_type_;
    +    OP_REQUIRES_OK(
    +        context, ValidateInput(indices_list_in, values_list_in, shapes_list_in,
    +                               dense_list_in, internal_type));
     
         std::vector<std::unique_ptr<ColumnInterface<InternalType>>> columns =
             GenerateColumnsFromInput<InternalType>(indices_list_in, values_list_in,
    @@ -756,6 +790,7 @@ class SparseCrossOp : public OpKernel {
      private:
       int64 num_buckets_;
       uint64 hash_key_;
    +  DataType internal_type_;
     };
     
     class SparseCrossV2Op : public OpKernel {
    @@ -773,8 +808,11 @@ class SparseCrossV2Op : public OpKernel {
         OP_REQUIRES_OK(context,
                        context->input_list("dense_inputs", &dense_list_in));
     
    -    OP_REQUIRES_OK(context, ValidateInput(indices_list_in, values_list_in,
    -                                          shapes_list_in, dense_list_in));
    +    // Set internal_type to invalid_type so that the check will be ignored.
    +    DataType internal_type = DT_INVALID;
    +    OP_REQUIRES_OK(
    +        context, ValidateInput(indices_list_in, values_list_in, shapes_list_in,
    +                               dense_list_in, internal_type));
     
         const Tensor* sep_t;
         OP_REQUIRES_OK(context, context->input("sep", &sep_t));
    @@ -832,8 +870,11 @@ class SparseCrossHashedOp : public OpKernel {
         OP_REQUIRES_OK(context,
                        context->input_list("dense_inputs", &dense_list_in));
     
    -    OP_REQUIRES_OK(context, ValidateInput(indices_list_in, values_list_in,
    -                                          shapes_list_in, dense_list_in));
    +    // Set internal_type to invalid_type so that the check will be ignored.
    +    DataType internal_type = DT_INVALID;
    +    OP_REQUIRES_OK(
    +        context, ValidateInput(indices_list_in, values_list_in, shapes_list_in,
    +                               dense_list_in, internal_type));
     
         const Tensor* num_buckets_t;
         OP_REQUIRES_OK(context, context->input("num_buckets", &num_buckets_t));
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.