CVE-2022-29208 (published 2022-05-20T23:15Z)

TensorFlow is an open source platform for machine learning. Prior to versions 2.9.0, 2.8.1, 2.7.2, and 2.6.4, the implementation of `tf.raw_ops.EditDistance` has incomplete validation. Users can pass negative values to cause a segmentation fault based denial of service. In multiple places throughout the code, one may compute an index for a write operation. However, the existing validation only checks against the upper bound of the array. Hence, it is possible to write before the array by massaging the input to generate negative values for `loc`. Versions 2.9.0, 2.8.1, 2.7.2, and 2.6.4 contain a patch for this issue.

Severity: LOW
CVSS v2 base score: 3.6 (AV:L/AC:L/Au:N/C:N/I:P/A:P)
CVSS v3 base score: 7.1, HIGH (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H)

Weakness information:
cwe_id: CWE-787
cwe_name: Out-of-bounds Write
description: The product writes data past the end, or before the beginning, of the intended buffer.
extended_description: 
            
            
             
			 
         
         

Fix information:
repo_url: https://github.com/tensorflow/tensorflow
commit_details: repo_url: https://github.com/tensorflow/tensorflow
author: Alan Liu
author_date: 2022-04-29 09:47:37-07:00
msg: Fix tf.raw_ops.EditDistance vulnerability with negative indices.

Check that indices are non-negative. Fix several identical code sites.
Clean up grammar in error message.

PiperOrigin-RevId: 445442017
repository: repo_url: https://github.com/tensorflow/tensorflow
repo_name: tensorflow/tensorflow
description: An Open Source Machine Learning Framework for Everyone
repo_language: C++
owner: tensorflow
file_changes: filename: edit_distance_op.cc
change_type: ModificationType.MODIFY
diff: @@ -203,9 +203,9 @@ class EditDistanceOp : public OpKernel {
         auto loc = std::inner_product(g_truth.begin(), g_truth.end(),
                                       output_strides.begin(), int64_t{0});
         OP_REQUIRES(
-            ctx, loc < output_elements,
+            ctx, 0 <= loc && loc < output_elements,
             errors::Internal("Got an inner product ", loc,
-                             " which would require in writing to outside of "
+                             " which would require writing to outside of "
                              "the buffer for the output tensor (max elements ",
                              output_elements, ")"));
         output_t(loc) =
@@ -218,9 +218,9 @@ class EditDistanceOp : public OpKernel {
         auto loc = std::inner_product(g_hypothesis.begin(), g_hypothesis.end(),
                                       output_strides.begin(), int64_t{0});
         OP_REQUIRES(
-            ctx, loc < output_elements,
+            ctx, 0 <= loc && loc < output_elements,
             errors::Internal("Got an inner product ", loc,
-                             " which would require in writing to outside of "
+                             " which would require writing to outside of "
                              "the buffer for the output tensor (max elements ",
                              output_elements, ")"));
         output_t(loc) = hypothesis_seq.size();
@@ -232,9 +232,9 @@ class EditDistanceOp : public OpKernel {
         auto loc = std::inner_product(g_truth.begin(), g_truth.end(),
                                       output_strides.begin(), int64_t{0});
         OP_REQUIRES(
-            ctx, loc < output_elements,
+            ctx, 0 <= loc && loc < output_elements,
             errors::Internal("Got an inner product ", loc,
-                             " which would require in writing to outside of "
+                             " which would require writing to outside of "
                              "the buffer for the output tensor (max elements ",
                              output_elements, ")"));
         output_t(loc) = (normalize_) ? 1.0 : truth_seq.size();
@@ -248,9 +248,9 @@ class EditDistanceOp : public OpKernel {
       auto loc = std::inner_product(g_hypothesis.begin(), g_hypothesis.end(),
                                     output_strides.begin(), int64_t{0});
       OP_REQUIRES(
-          ctx, loc < output_elements,
+          ctx, 0 <= loc && loc < output_elements,
           errors::Internal("Got an inner product ", loc,
-                           " which would require in writing to outside of the "
+                           " which would require writing to outside of the "
                            "buffer for the output tensor (max elements ",
                            output_elements, ")"));
       output_t(loc) = hypothesis_seq.size();
@@ -266,9 +266,9 @@ class EditDistanceOp : public OpKernel {
       auto loc = std::inner_product(g_truth.begin(), g_truth.end(),
                                     output_strides.begin(), int64_t{0});
       OP_REQUIRES(
-          ctx, loc < output_elements,
+          ctx, 0 <= loc && loc < output_elements,
           errors::Internal("Got an inner product ", loc,
-                           " which would require in writing to outside of the "
+                           " which would require writing to outside of the "
                            "buffer for the output tensor (max elements ",
                            output_elements, ")"));
       output_t(loc) = (normalize_) ? 1.0 : truth_seq.size();

programming_language: C++
filename: edit_distance_op_test.py
change_type: ModificationType.MODIFY
diff: @@ -207,6 +207,24 @@ class EditDistanceTest(test.TestCase):
         normalize=True,
         expected_output=expected_output)
 
+  def testEditDistanceBadIndices(self):
+    hypothesis_indices = np.full((3, 3), -1250999896764, dtype=np.int64)
+    hypothesis_values = np.empty(3, dtype=np.int64)
+    hypothesis_shape = np.empty(3, dtype=np.int64)
+    truth_indices = np.full((3, 3), -1250999896764, dtype=np.int64)
+    truth_values = np.full([3], 2, dtype=np.int64)
+    truth_shape = np.full([3], 2, dtype=np.int64)
+    expected_output = []  # dummy; ignored
+
+    self._testEditDistance(
+        hypothesis=(hypothesis_indices, hypothesis_values, hypothesis_shape),
+        truth=(truth_indices, truth_values, truth_shape),
+        normalize=False,
+        expected_output=expected_output,
+        expected_err_re=(r"inner product -\d+ which would require writing "
+                         "to outside of the buffer for the output tensor")
+    )
+
 
 if __name__ == "__main__":
   test.main()

programming_language: Python