VYPR
High severityNVD Advisory· Published Feb 3, 2022· Updated May 5, 2025

Heap overflow in Tensorflow

CVE-2022-21740

Description

A heap overflow in TensorFlow's SparseCountSparseOutput can lead to memory corruption, fixed in 2.8.0 and backported.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A heap overflow in TensorFlow's `SparseCountSparseOutput` can lead to memory corruption, fixed in 2.8.0 and backported.

Vulnerability

A heap overflow vulnerability exists in TensorFlow's implementation of SparseCountSparseOutput, specifically in the SparseCount kernel (located in tensorflow/core/kernels/count_ops.cc at lines 168–273 [1]). The bug occurs when the operator processes malformed or specially crafted sparse tensor inputs, lacking sufficient validation for tensor shapes and dimensions. Affected versions include TensorFlow 2.5.3, 2.6.3, 2.7.1, and all prior releases in these branches; the fix is included in TensorFlow 2.8.0 and later [1][3].

Exploitation

An attacker must be able to supply a crafted sparse tensor to the SparseCountSparseOutput op, typically via a TensorFlow model or a direct API call. No special network position is required if the model accepts arbitrary input; authentication may be needed depending on deployment. The attacker provides malicious indices, values, and shape tensors that bypass insufficient checks, triggering a heap overflow [1][3].

Impact

Successful exploitation results in heap memory corruption, potentially leading to arbitrary code execution or a denial of service via crash. The scope of compromise is limited to the TensorFlow process; however, this could allow an attacker to read or modify data in memory [1].

Mitigation

The vulnerability is fixed in TensorFlow 2.8.0, released on 2022-02-03. The commit 2b7100d has been cherry-picked to TensorFlow 2.7.1, 2.6.3, and 2.5.3 [1][3]. Users should upgrade to the latest patched version for their branch. If upgrading is not possible, avoid processing untrusted sparse tensor inputs.

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
tensorflowPyPI
< 2.5.32.5.3
tensorflowPyPI
>= 2.6.0, < 2.6.32.6.3
tensorflowPyPI
>= 2.7.0, < 2.7.12.7.1
tensorflow-cpuPyPI
< 2.5.32.5.3
tensorflow-cpuPyPI
>= 2.6.0, < 2.6.32.6.3
tensorflow-cpuPyPI
>= 2.7.0, < 2.7.12.7.1
tensorflow-gpuPyPI
< 2.5.32.5.3
tensorflow-gpuPyPI
>= 2.6.0, < 2.6.32.6.3
tensorflow-gpuPyPI
>= 2.7.0, < 2.7.12.7.1

Affected products

5

Patches

2
adbbabdb0d3a

Further validate sparse tensor for `SparseCount`: indices must be valid within dense shape.

https://github.com/tensorflow/tensorflowMihai MaruseacDec 8, 2021via ghsa
1 file changed · +17 3
  • tensorflow/core/kernels/count_ops.cc+17 3 modified
    @@ -206,6 +206,23 @@ class SparseCount : public OpKernel {
         OP_REQUIRES(context, shape.NumElements() > 0,
                     errors::InvalidArgument(
                         "The shape argument requires at least one element."));
    +    // Validate indices: each index must be valid for the corresponding
    +    // dimension. This could be possibly done better.
    +    const auto indices_values = indices.matrix<int64_t>();
    +    const auto shape_vector = shape.vec<int64_t>();
    +    int num_values = values.NumElements();  // same as first dim of indices
    +    int rank = indices.shape().dim_size(1);
    +    for (int i = 0; i < num_values; ++i) {
    +      for (int j = 0; j < rank; ++j) {
    +        OP_REQUIRES(
    +            context,
    +            indices_values(i, j) >= 0 && indices_values(i, j) < shape_vector(j),
    +            errors::InvalidArgument(
    +                "Invalid index value at ", i, ": dimension ", j, " has value ",
    +                indices_values(i, j), " which is not in [0, ", shape_vector(j),
    +                ") (as given by dense shape ", shape.DebugString()));
    +      }
    +    }
     
         if (use_weights) {
           OP_REQUIRES(
    @@ -217,11 +234,8 @@ class SparseCount : public OpKernel {
         }
     
         bool is_1d = shape.NumElements() == 1;
    -    auto shape_vector = shape.flat<int64_t>();
         int num_batches = is_1d ? 1 : shape_vector(0);
    -    int num_values = values.NumElements();
     
    -    const auto indices_values = indices.matrix<int64_t>();
         const auto values_values = values.flat<T>();
         const auto weight_values = weights.flat<W>();
     
    
2b7100d6cdff

Cleanup and remove duplicate validation in `SparseCount`.

https://github.com/tensorflow/tensorflowMihai MaruseacDec 8, 2021via ghsa
1 file changed · +21 27
  • tensorflow/core/kernels/count_ops.cc+21 27 modified
    @@ -185,6 +185,27 @@ class SparseCount : public OpKernel {
                     errors::InvalidArgument(
                         "Input indices must be a 2-dimensional tensor. Got: ",
                         indices.shape().DebugString()));
    +    OP_REQUIRES(context, TensorShapeUtils::IsVector(values.shape()),
    +                errors::InvalidArgument("Input values must be a vector. Got: ",
    +                                        values.shape().DebugString()));
    +    OP_REQUIRES(context, TensorShapeUtils::IsVector(shape.shape()),
    +                errors::InvalidArgument("Input shape must be a vector. Got: ",
    +                                        shape.shape().DebugString()));
    +    OP_REQUIRES(context,
    +                values.shape().dim_size(0) == indices.shape().dim_size(0),
    +                errors::InvalidArgument(
    +                    "Number of values must match first dimension of indices.",
    +                    "Got ", values.shape().dim_size(0),
    +                    " values, indices shape: ", indices.shape().DebugString()));
    +    OP_REQUIRES(
    +        context, shape.shape().dim_size(0) == indices.shape().dim_size(1),
    +        errors::InvalidArgument(
    +            "Number of dimensions must match second dimension of indices.",
    +            "Got ", shape.shape().dim_size(0),
    +            " dimensions, indices shape: ", indices.shape().DebugString()));
    +    OP_REQUIRES(context, shape.NumElements() > 0,
    +                errors::InvalidArgument(
    +                    "The shape argument requires at least one element."));
     
         if (use_weights) {
           OP_REQUIRES(
    @@ -195,28 +216,11 @@ class SparseCount : public OpKernel {
                   "; values shape: ", values.shape().DebugString()));
         }
     
    -    OP_REQUIRES(context, shape.NumElements() != 0,
    -                errors::InvalidArgument(
    -                    "The shape argument requires at least one element."));
    -
         bool is_1d = shape.NumElements() == 1;
         auto shape_vector = shape.flat<int64_t>();
         int num_batches = is_1d ? 1 : shape_vector(0);
         int num_values = values.NumElements();
     
    -    for (int b = 0; b < shape_vector.size(); b++) {
    -      OP_REQUIRES(context, shape_vector(b) >= 0,
    -                  errors::InvalidArgument(
    -                      "Elements in dense_shape must be >= 0. Instead got:",
    -                      shape.DebugString()));
    -    }
    -
    -    OP_REQUIRES(context, num_values == indices.shape().dim_size(0),
    -                errors::InvalidArgument(
    -                    "Number of values must match first dimension of indices.",
    -                    "Got ", num_values,
    -                    " values, indices shape: ", indices.shape().DebugString()));
    -
         const auto indices_values = indices.matrix<int64_t>();
         const auto values_values = values.flat<T>();
         const auto weight_values = weights.flat<W>();
    @@ -225,16 +229,6 @@ class SparseCount : public OpKernel {
     
         T max_value = 0;
     
    -    OP_REQUIRES(context, num_values <= indices.shape().dim_size(0),
    -                errors::InvalidArgument(
    -                    "The first dimension of indices must be equal to or "
    -                    "greather than number of values. ( ",
    -                    indices.shape().dim_size(0), " vs. ", num_values, " )"));
    -    OP_REQUIRES(context, indices.shape().dim_size(1) > 0,
    -                errors::InvalidArgument("The second dimension of indices must "
    -                                        "be greater than 0. Received: ",
    -                                        indices.shape().dim_size(1)));
    -
         for (int idx = 0; idx < num_values; ++idx) {
           int batch = is_1d ? 0 : indices_values(idx, 0);
           if (batch >= num_batches) {
    

Vulnerability mechanics

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

References

8

News mentions

0

No linked articles in our index yet.