CVE-2022-41897: Out-of-bounds Read (CWE-125)
value: TensorFlow is an open source platform for machine learning. If `FractionMaxPoolGrad` is given outsize inputs `row_pooling_sequence` and `col_pooling_sequence`, TensorFlow will crash. We have patched the issue in GitHub commit d71090c3e5ca325bdf4b02eb236cfb3ee823e927. The fix will be included in TensorFlow 2.11. We will also cherrypick this commit on TensorFlow 2.10.1, 2.9.3, and TensorFlow 2.8.4, as these are also affected and still in supported range.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.5
Published: 2022-11-18T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/fractional_max_pool_op.cc, tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py
Commit date: 2022-09-28 11:14:02 -0700
Commit message: Fix security vulnerability with FractionalMaxPoolGrad

PiperOrigin-RevId: 477500477

Diff: diff --git a/tensorflow/core/kernels/fractional_max_pool_op.cc b/tensorflow/core/kernels/fractional_max_pool_op.cc
index 375786615ebe6..3ea45277bb5a4 100644
--- a/tensorflow/core/kernels/fractional_max_pool_op.cc
+++ b/tensorflow/core/kernels/fractional_max_pool_op.cc
@@ -256,10 +256,22 @@ class FractionalMaxPoolGradOp : public OpKernel {
                     "orig_output should be a tensor of rank 4, got ",
                     tensor_out.DebugString()));
     OP_REQUIRES(context, tensor_out.NumElements() > 0,
                 errors::InvalidArgument("orig_output must not be empty, got ",
                                         tensor_out.DebugString()));
+    OP_REQUIRES(
+        context,
+        height_seq_tensor.NumElements() * width_seq_tensor.NumElements() <=
+            tensor_in.NumElements(),
+        errors::InvalidArgument(
+            "Pooling region has more elements than the input tensor. "
+            "row_pooling_sequence: ",
+            height_seq_tensor.DebugString(),
+            "col_pooling_sequence: ", width_seq_tensor.DebugString(),
+            "orig_input: ", tensor_in.DebugString()));
+
+    //
     std::vector<int64_t> input_size(tensor_in_and_out_dims);
     std::vector<int64_t> output_size(tensor_in_and_out_dims);
     for (int i = 0; i < tensor_in_and_out_dims; ++i) {
       input_size[i] = tensor_in.dim_size(i);
     }
diff --git a/tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py b/tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py
index 1594844ab49e7..79b2c799d58e3 100644
--- a/tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py
+++ b/tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py
@@ -630,11 +630,11 @@ class FractionalMaxPoolGradTest(test.TestCase):
       self.assertAllClose(expected_input_backprop_overlapping,
                           input_backprop_overlapping)
 
   def testInvalidSeqRaiseErrorForFractionalMaxPoolGrad(self):
     with self.assertRaises(errors.InvalidArgumentError):
-      with self.cached_session() as _:
+      with self.cached_session():
         overlapping = True
         orig_input = constant_op.constant(
             .453409232, shape=[1, 7, 13, 1], dtype=dtypes.float32)
         orig_output = constant_op.constant(
             .453409232, shape=[1, 7, 13, 1], dtype=dtypes.float32)
@@ -651,8 +651,26 @@ class FractionalMaxPoolGradTest(test.TestCase):
             row_pooling_sequence=row_pooling_sequence,
             col_pooling_sequence=col_pooling_sequence,
             overlapping=overlapping)
         self.evaluate(t)
 
+  def testOverLargeSeqRaiseErrorForFractionalMaxPoolGrad(self):
+    with self.assertRaises(errors.InvalidArgumentError):
+      with self.cached_session():
+        overlapping = False
+        orig_input = [[[[1, 1, 1, 1, 1]]]]
+        orig_output = [[[[1, 1, 1]]]]
+        out_backprop = [[[[3], [3], [6]]]]
+        row_pooling_sequence = [-0x4000000, 1, 1]
+        col_pooling_sequence = [-0x4000000, 1, 1]
+        t = gen_nn_ops.FractionalMaxPoolGrad(
+            orig_input=orig_input,
+            orig_output=orig_output,
+            out_backprop=out_backprop,
+            row_pooling_sequence=row_pooling_sequence,
+            col_pooling_sequence=col_pooling_sequence,
+            overlapping=overlapping)
+        self.evaluate(t)
+
 
 if __name__ == "__main__":
   test.main()

Vulnerable code:       with self.cached_session() as _:
Fixed code:     OP_REQUIRES(
        context,
        height_seq_tensor.NumElements() * width_seq_tensor.NumElements() <=
            tensor_in.NumElements(),
        errors::InvalidArgument(
            "Pooling region has more elements than the input tensor. "
            "row_pooling_sequence: ",
            height_seq_tensor.DebugString(),
            "col_pooling_sequence: ", width_seq_tensor.DebugString(),
            "orig_input: ", tensor_in.DebugString()));

    //
      with self.cached_session():
  def testOverLargeSeqRaiseErrorForFractionalMaxPoolGrad(self):
    with self.assertRaises(errors.InvalidArgumentError):
      with self.cached_session():
        overlapping = False
        orig_input = [[[[1, 1, 1, 1, 1]]]]
        orig_output = [[[[1, 1, 1]]]]
        out_backprop = [[[[3], [3], [6]]]]
        row_pooling_sequence = [-0x4000000, 1, 1]
        col_pooling_sequence = [-0x4000000, 1, 1]
        t = gen_nn_ops.FractionalMaxPoolGrad(
            orig_input=orig_input,
            orig_output=orig_output,
            out_backprop=out_backprop,
            row_pooling_sequence=row_pooling_sequence,
            col_pooling_sequence=col_pooling_sequence,
            overlapping=overlapping)
        self.evaluate(t)