CVE-2022-41886: Incorrect Calculation of Buffer Size (CWE-131)
value: TensorFlow is an open source platform for machine learning. When `tf.raw_ops.ImageProjectiveTransformV2` is given a large output shape, it overflows. We have patched the issue in GitHub commit 8faa6ea692985dbe6ce10e1a3168e0bd60a723ba. 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 does not correctly calculate the size to be used when allocating a buffer, which could lead to a buffer overflow.
CVSS v3 base score: 7.5
Published: 2022-11-18T22:15Z
Repository: https://github.com/tensorflow/tensorflow
Language: Python
Files changed: tensorflow/core/kernels/image/image_ops.cc, tensorflow/python/ops/image_ops_test.py
Commit date: 2022-10-05 13:23:22 -0700
Commit message: Fix tf.raw_ops.ImageProjectiveTransformV2 vulnerability with large output_shape.

Note: This fix will have to be cherry picked in r2.10, r2.9, and r2.8.
PiperOrigin-RevId: 479125772

Diff: diff --git a/tensorflow/core/kernels/image/image_ops.cc b/tensorflow/core/kernels/image/image_ops.cc
index c2e769f146c76..113a9b2af9a82 100644
--- a/tensorflow/core/kernels/image/image_ops.cc
+++ b/tensorflow/core/kernels/image/image_ops.cc
@@ -94,15 +94,16 @@ void DoImageProjectiveTransformOp(OpKernelContext* ctx,
                                         fill_value_t.shape().DebugString()));
     fill_value = static_cast<T>(*(fill_value_t.scalar<float>().data()));
   }
 
   Tensor* output_t;
+  TensorShape output_shape;
   OP_REQUIRES_OK(
-      ctx, ctx->allocate_output(0,
-                                TensorShape({images_t.dim_size(0), out_height,
-                                             out_width, images_t.dim_size(3)}),
-                                &output_t));
+      ctx, TensorShape::BuildTensorShape({images_t.dim_size(0), out_height,
+                                          out_width, images_t.dim_size(3)},
+                                         &output_shape));
+  OP_REQUIRES_OK(ctx, ctx->allocate_output(0, output_shape, &output_t));
   auto output = output_t->tensor<T, 4>();
   auto images = images_t.tensor<T, 4>();
   auto transform = transform_t.matrix<float>();
 
   (FillProjectiveTransform<Device, T>(interpolation))(
diff --git a/tensorflow/python/ops/image_ops_test.py b/tensorflow/python/ops/image_ops_test.py
index 11a673d24ce4f..66dd42d7e6a89 100644
--- a/tensorflow/python/ops/image_ops_test.py
+++ b/tensorflow/python/ops/image_ops_test.py
@@ -2333,10 +2333,33 @@ class PadToBoundingBoxTest(test_util.TensorFlowTestCase,
             offset_height=1,
             offset_width=1)
         self.evaluate(v)
 
 
+class ImageProjectiveTransformV2(test_util.TensorFlowTestCase):
+
+  def testShapeTooLarge(self):
+    interpolation = "BILINEAR"
+    fill_mode = "REFLECT"
+    images = constant_op.constant(
+        0.184634328, shape=[2, 5, 8, 3], dtype=dtypes.float32)
+    transforms = constant_op.constant(
+        0.378575385, shape=[2, 8], dtype=dtypes.float32)
+    output_shape = constant_op.constant([1879048192, 1879048192],
+                                        shape=[2],
+                                        dtype=dtypes.int32)
+    with self.assertRaisesRegex(errors.InvalidArgumentError,
+                                r"Encountered overflow when multiplying"):
+      self.evaluate(
+          gen_image_ops.ImageProjectiveTransformV2(
+              images=images,
+              transforms=transforms,
+              output_shape=output_shape,
+              interpolation=interpolation,
+              fill_mode=fill_mode))
+
+
 class InternalPadToBoundingBoxTest(test_util.TensorFlowTestCase,
                                    parameterized.TestCase):
 
   def _InternalPadToBoundingBox(self, x, offset_height, offset_width,
                                 target_height, target_width, use_tensor_inputs):

Vulnerable code:       ctx, ctx->allocate_output(0,
                                TensorShape({images_t.dim_size(0), out_height,
                                             out_width, images_t.dim_size(3)}),
                                &output_t));
Fixed code:   TensorShape output_shape;
      ctx, TensorShape::BuildTensorShape({images_t.dim_size(0), out_height,
                                          out_width, images_t.dim_size(3)},
                                         &output_shape));
  OP_REQUIRES_OK(ctx, ctx->allocate_output(0, output_shape, &output_t));
class ImageProjectiveTransformV2(test_util.TensorFlowTestCase):

  def testShapeTooLarge(self):
    interpolation = "BILINEAR"
    fill_mode = "REFLECT"
    images = constant_op.constant(
        0.184634328, shape=[2, 5, 8, 3], dtype=dtypes.float32)
    transforms = constant_op.constant(
        0.378575385, shape=[2, 8], dtype=dtypes.float32)
    output_shape = constant_op.constant([1879048192, 1879048192],
                                        shape=[2],
                                        dtype=dtypes.int32)
    with self.assertRaisesRegex(errors.InvalidArgumentError,
                                r"Encountered overflow when multiplying"):
      self.evaluate(
          gen_image_ops.ImageProjectiveTransformV2(
              images=images,
              transforms=transforms,
              output_shape=output_shape,
              interpolation=interpolation,
              fill_mode=fill_mode))