CVE-2022-35990 (Python, published 2022-09-16T22:15Z)
Description: value: TensorFlow is an open source platform for machine learning. When `tf.quantization.fake_quant_with_min_max_vars_per_channel_gradient` receives input `min` or `max` of rank other than 1, it gives a `CHECK` fail that can trigger a denial of service attack. We have patched the issue in GitHub commit f3cf67ac5705f4f04721d15e485e192bb319feed. The fix will be included in TensorFlow 2.10.0. We will also cherrypick this commit on TensorFlow 2.9.1, TensorFlow 2.8.1, and TensorFlow 2.7.2, as these are also affected and still in supported range.There are no known workarounds for this issue.
Severity: nan (CVSS v3 base score: 7.5)
Weakness: CWE-617 \u2014 Reachable Assertion
The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary.
Repository: https://github.com/tensorflow/tensorflow
Files changed:
tensorflow/core/kernels/fake_quant_ops.cc
tensorflow/python/kernel_tests/quantization_ops/quantization_ops_test.py
Commit message: Add IsScalar / IsVector (rank) checks to input min/max tensors for FakeQuantWithMinMaxVarsPerChannelGradientOp and FakeQuantWithMinMaxVarsGradientOp.

PiperOrigin-RevId: 462542629


Vulnerable code:
          math_ops.quantize_down_and_shrink_range(input=inputs,
                                                  input_min=[],
                                                  input_max=4.0,
                                                  out_type=dtypes.quint8))

Fixed code:
    OP_REQUIRES(
        context, TensorShapeUtils::IsScalar(min.shape()),
        InvalidArgument("`min` must be rank 0 but is rank ", min.dims()));
    OP_REQUIRES(
        context, TensorShapeUtils::IsScalar(max.shape()),
        InvalidArgument("`max` must be rank 0 but is rank ", max.dims()));
    OP_REQUIRES(
        context, TensorShapeUtils::IsVector(min.shape()),
        InvalidArgument("`min` must be rank 1 but is rank ", min.dims()));
    OP_REQUIRES(
        context, TensorShapeUtils::IsVector(max.shape()),
        InvalidArgument("`max` must be rank 1 but is rank ", max.dims()));
class FakeQuantWithMinMaxVarsGradientOpTest(test_util.TensorFlowTestCase):

  @test_util.run_in_graph_and_eager_modes
  def test_invalid_inputs(self):
    gradients = constant_op.constant(
        value=[[1.0], [2.0], [4.0]], dtype=dtypes.float32)
    inputs = constant_op.constant(
        value=[[1.0], [2.0], [4.0]], dtype=dtypes.float32)

    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                "must be equal rank|must be rank 0"):
      self.evaluate(
          array_ops.fake_quant_with_min_max_vars_gradient(
              gradients=gradients,
              inputs=inputs,
              min=0.0,
              max=[[1.0], [2.0], [4.0]]))

    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                "must be rank 0"):
      self.evaluate(
          array_ops.fake_quant_with_min_max_vars_gradient(
              gradients=gradients,
              inputs=inputs,
              min=[[1.0], [2.0], [4.0]],
              max=[[1.0], [2.0], [4.0]]))


class FakeQuantWithMinMaxVarsPerChannelGradientOpTest(
    test_util.TensorFlowTestCase):

  @test_util.run_in_graph_and_eager_modes
  def test_invalid_inputs(self):
    gradients = constant_op.constant(
        value=[[1.0], [2.0], [4.0]], dtype=dtypes.float32)
    inputs = constant_op.constant(
        value=[[1.0], [2.0], [4.0]], dtype=dtypes.float32)

    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                "Shapes must be equal rank|must be rank 1"):
      self.evaluate(
          array_ops.fake_quant_with_min_max_vars_per_channel_gradient(
              gradients=gradients, inputs=inputs, min=[[0.0]], max=[1.0]))

    with self.assertRaisesRegex(
        (ValueError, errors.InvalidArgumentError),
        "Dimension 0 in both shapes must be equal|incorrect size"):
      self.evaluate(
          array_ops.fake_quant_with_min_max_vars_per_channel_gradient(
              gradients=gradients, inputs=inputs, min=[0.0, 0.1], max=[1.0]))

    with self.assertRaisesRegex((ValueError, errors.InvalidArgumentError),
                                "Shapes must be equal rank|must be rank 1"):
      self.evaluate(
          array_ops.fake_quant_with_min_max_vars_per_channel_gradient(
              gradients=gradients, inputs=inputs, min=[1.0], max=[[1.0]]))

    with self.assertRaisesRegex(
        (ValueError, errors.InvalidArgumentError),
        "Dimension 0 in both shapes must be equal|incorrect size"):
      self.evaluate(
          array_ops.fake_quant_with_min_max_vars_per_channel_gradient(
              gradients=gradients, inputs=inputs, min=[0.0], max=[1.0, 1.1]))


          math_ops.quantize_down_and_shrink_range(
              input=inputs, input_min=[], input_max=4.0,
              out_type=dtypes.quint8))