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

Stack overflow in `ParseAttrValue` with nested tensors

CVE-2021-29615

Description

TensorFlow is an end-to-end open source platform for machine learning. The implementation of ParseAttrValue(https://github.com/tensorflow/tensorflow/blob/c22d88d6ff33031aa113e48aa3fc9aa74ed79595/tensorflow/core/framework/attr_value_util.cc#L397-L453) can be tricked into stack overflow due to recursion by giving in a specially crafted input. 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
e07e1c3d2649

Prevent memory overflow in ParseAttrValue from nested tensors.

https://github.com/tensorflow/tensorflowLaura PakApr 23, 2021via ghsa
1 file changed · +57 1
  • tensorflow/core/framework/attr_value_util.cc+57 1 modified
    @@ -38,6 +38,9 @@ namespace {
     // Do not construct large tensors to compute their hash or compare for equality.
     constexpr int kMaxAttrValueTensorByteSize = 32 * 1024 * 1024;  // 32mb
     
    +// Limit nesting of tensors to 100 deep to prevent memory overflow.
    +constexpr int kMaxTensorNestDepth = 100;
    +
     // Return the size of the tensor represented by this TensorProto. If shape is
     // not fully defined return -1.
     int64 TensorByteSize(const TensorProto& t) {
    @@ -224,6 +227,54 @@ string SummarizeFunc(const NameAttrList& func) {
       return strings::StrCat(func.name(), "[", absl::StrJoin(entries, ", "), "]");
     }
     
    +bool ParseAttrValueHelper_TensorNestsUnderLimit(int limit, string to_parse) {
    +  int nests = 0;
    +  int maxed_out = to_parse.length();
    +  int open_curly = to_parse.find('{');
    +  int open_bracket = to_parse.find('<');
    +  int close_curly = to_parse.find('}');
    +  int close_bracket = to_parse.find('>');
    +  if (open_curly == -1) {
    +    open_curly = maxed_out;
    +  }
    +  if (open_bracket == -1) {
    +    open_bracket = maxed_out;
    +  }
    +  int min = std::min(open_curly, open_bracket);
    +  do {
    +    if (open_curly == maxed_out && open_bracket == maxed_out) {
    +      return true;
    +    }
    +    if (min == open_curly) {
    +      nests += 1;
    +      open_curly = to_parse.find('{', open_curly + 1);
    +      if (open_curly == -1) {
    +        open_curly = maxed_out;
    +      }
    +    } else if (min == open_bracket) {
    +      nests += 1;
    +      open_bracket = to_parse.find('<', open_bracket + 1);
    +      if (open_bracket == -1) {
    +        open_bracket = maxed_out;
    +      }
    +    } else if (min == close_curly) {
    +      nests -= 1;
    +      close_curly = to_parse.find('}', close_curly + 1);
    +      if (close_curly == -1) {
    +        close_curly = maxed_out;
    +      }
    +    } else if (min == close_bracket) {
    +      nests -= 1;
    +      close_bracket = to_parse.find('>', close_bracket + 1);
    +      if (close_bracket == -1) {
    +        close_bracket = maxed_out;
    +      }
    +    }
    +    min = std::min({open_curly, open_bracket, close_curly, close_bracket});
    +  } while (nests < 100);
    +  return false;
    +}
    +
     }  // namespace
     
     string SummarizeAttrValue(const AttrValue& attr_value) {
    @@ -448,7 +499,12 @@ bool ParseAttrValue(StringPiece type, StringPiece text, AttrValue* out) {
       } else {
         to_parse = strings::StrCat(field_name, ": ", text);
       }
    -
    +  if (field_name == "tensor") {
    +    if (!ParseAttrValueHelper_TensorNestsUnderLimit(kMaxTensorNestDepth,
    +                                                    to_parse)) {
    +      return false;
    +    }
    +  }
       return ProtoParseFromString(to_parse, out);
     }
     
    

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.