diff options
author | A. Unique TensorFlower <gardener@tensorflow.org> | 2022-10-24 14:30:10 -0700 |
---|---|---|
committer | TensorFlow Release Automation <jenkins@tensorflow.org> | 2022-11-14 22:34:45 +0000 |
commit | ea08e8b7f49641cfb7080759b051dd77a8c69274 (patch) | |
tree | be4d475b5b3865470c85e4016c8c3d2bdaa4e0d7 | |
parent | f52e0aefe44b643b9cf3474834ab9bbb59c7e7dc (diff) | |
download | tensorflow-ea08e8b7f49641cfb7080759b051dd77a8c69274.tar.gz |
Fix security vulnerability with FractionalMax(AVG)Pool with illegal pooling_ratio
PiperOrigin-RevId: 483486453
-rw-r--r-- | tensorflow/core/kernels/fractional_avg_pool_op.cc | 14 | ||||
-rw-r--r-- | tensorflow/core/kernels/fractional_max_pool_op.cc | 6 | ||||
-rw-r--r-- | tensorflow/core/ops/nn_ops.cc | 7 | ||||
-rw-r--r-- | tensorflow/core/ops/nn_ops_test.cc | 13 | ||||
-rw-r--r-- | tensorflow/python/kernel_tests/nn_ops/fractional_avg_pool_op_test.py | 35 | ||||
-rw-r--r-- | tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py | 19 |
6 files changed, 84 insertions, 10 deletions
diff --git a/tensorflow/core/kernels/fractional_avg_pool_op.cc b/tensorflow/core/kernels/fractional_avg_pool_op.cc index e1c536af706..3bb20686608 100644 --- a/tensorflow/core/kernels/fractional_avg_pool_op.cc +++ b/tensorflow/core/kernels/fractional_avg_pool_op.cc @@ -44,6 +44,12 @@ class FractionalAvgPoolOp : public OpKernel { OP_REQUIRES(context, pooling_ratio_.size() == 4, errors::InvalidArgument( "pooling_ratio field must specify 4 dimensions")); + for (std::size_t i = 0; i < pooling_ratio_.size(); ++i) { + OP_REQUIRES(context, pooling_ratio_[i] >= 1, + errors::InvalidArgument( + "pooling_ratio cannot be smaller than 1, got: ", + pooling_ratio_[i])); + } OP_REQUIRES( context, pooling_ratio_[0] == 1 || pooling_ratio_[3] == 1, errors::Unimplemented("Fractional average pooling is not yet " @@ -82,9 +88,11 @@ class FractionalAvgPoolOp : public OpKernel { for (int i = 0; i < tensor_in_and_out_dims; ++i) { input_size[i] = tensor_in.dim_size(i); OP_REQUIRES( - context, pooling_ratio_[i] <= input_size[i], - errors::InvalidArgument( - "Pooling ratio cannot be bigger than input tensor dim size.")); + context, input_size[i] >= pooling_ratio_[i], + errors::InvalidArgument("Pooling ratio is higher than input " + "dimension size for dimension ", + i, ". Input dim size: ", input_size[i], + " pooling ratio: ", pooling_ratio_[i])); } // Output size. for (int i = 0; i < tensor_in_and_out_dims; ++i) { diff --git a/tensorflow/core/kernels/fractional_max_pool_op.cc b/tensorflow/core/kernels/fractional_max_pool_op.cc index 3ea45277bb5..ec08b5c5028 100644 --- a/tensorflow/core/kernels/fractional_max_pool_op.cc +++ b/tensorflow/core/kernels/fractional_max_pool_op.cc @@ -45,6 +45,12 @@ class FractionalMaxPoolOp : public OpKernel { OP_REQUIRES(context, pooling_ratio_.size() == 4, errors::InvalidArgument("pooling_ratio field must " "specify 4 dimensions")); + for (std::size_t i = 0; i < pooling_ratio_.size(); ++i) { + OP_REQUIRES(context, pooling_ratio_[i] >= 1, + errors::InvalidArgument( + "pooling_ratio cannot be smaller than 1, got: ", + pooling_ratio_[i])); + } OP_REQUIRES( context, pooling_ratio_[0] == 1 || pooling_ratio_[3] == 1, diff --git a/tensorflow/core/ops/nn_ops.cc b/tensorflow/core/ops/nn_ops.cc index ee62330d158..9171f946783 100644 --- a/tensorflow/core/ops/nn_ops.cc +++ b/tensorflow/core/ops/nn_ops.cc @@ -60,6 +60,13 @@ Status FractionalPoolShapeFn(InferenceContext* c) { } } + for (std::size_t i = 0; i < pooling_ratio.size(); ++i) { + if (pooling_ratio[i] < 1) { + return errors::InvalidArgument( + "pooling_ratio cannot be smaller than 1, got: ", pooling_ratio[i]); + } + } + c->set_output(0, c->MakeShape(output_dims)); c->set_output(1, c->Vector(output_dims[1])); c->set_output(2, c->Vector(output_dims[2])); diff --git a/tensorflow/core/ops/nn_ops_test.cc b/tensorflow/core/ops/nn_ops_test.cc index 469a9015a17..41940da69ef 100644 --- a/tensorflow/core/ops/nn_ops_test.cc +++ b/tensorflow/core/ops/nn_ops_test.cc @@ -523,7 +523,8 @@ TEST(NNOpsTest, FractionalPool_ShapeFn) { .Finalize(&op.node_def)); }; - set_op(std::vector<float>{2.0f, 1, 1 / 1.5f, 1 / 2.0f}); + // pooling_ratio must >= 1.0 + set_op(std::vector<float>{2.0f, 1, 1.5f, 4.0f}); // Rank check. INFER_ERROR("must be rank 4", op, "[?,?,?]"); @@ -532,11 +533,11 @@ TEST(NNOpsTest, FractionalPool_ShapeFn) { INFER_OK(op, "?", "[?,?,?,?];[?];[?]"); INFER_OK(op, "[?,?,?,?]", "[?,?,?,?];[?];[?]"); - INFER_OK(op, "[10,20,30,40]", "[5,20,45,80];[20];[45]"); - INFER_OK(op, "[?,20,30,40]", "[?,20,45,80];[20];[45]"); - INFER_OK(op, "[10,?,30,40]", "[5,?,45,80];[?];[45]"); - INFER_OK(op, "[10,20,?,40]", "[5,20,?,80];[20];[?]"); - INFER_OK(op, "[10,20,30,?]", "[5,20,45,?];[20];[45]"); + INFER_OK(op, "[10,20,30,40]", "[5,20,20,10];[20];[20]"); + INFER_OK(op, "[?,20,30,40]", "[?,20,20,10];[20];[20]"); + INFER_OK(op, "[10,?,30,40]", "[5,?,20,10];[?];[20]"); + INFER_OK(op, "[10,20,?,40]", "[5,20,?,10];[20];[?]"); + INFER_OK(op, "[10,20,30,?]", "[5,20,20,?];[20];[20]"); // Wrong number of values for pooling_ratio. set_op(std::vector<float>{.5, 1.0, 1.5}); diff --git a/tensorflow/python/kernel_tests/nn_ops/fractional_avg_pool_op_test.py b/tensorflow/python/kernel_tests/nn_ops/fractional_avg_pool_op_test.py index 642a9d4a880..59b20de84b4 100644 --- a/tensorflow/python/kernel_tests/nn_ops/fractional_avg_pool_op_test.py +++ b/tensorflow/python/kernel_tests/nn_ops/fractional_avg_pool_op_test.py @@ -333,6 +333,41 @@ class FractionalAvgTest(test.TestCase): self.evaluate(z) + def testPoolingRatioHasMoreDimThanInput(self): + with self.cached_session() as _: + with self.assertRaisesRegex( + errors.InvalidArgumentError, + r"Pooling ratio is higher than input dimension size for dimension 1.*" + ): + result = nn_ops.gen_nn_ops.fractional_avg_pool( + value=constant_op.constant( + value=[[[[1, 4, 2, 3]]]], dtype=dtypes.int64), + pooling_ratio=[1.0, 1.44, 1.73, 1.0], + pseudo_random=False, + overlapping=False, + deterministic=False, + seed=0, + seed2=0, + name=None) + self.evaluate(result) + + def testPoolingRatioValueOutOfRange(self): + with self.cached_session() as _: + # Whether turn on `TF2_BEHAVIOR` generates different error messages + with self.assertRaisesRegex( + (errors.InvalidArgumentError, ValueError), + r"(pooling_ratio cannot be smaller than 1, got: .*)|(is negative)"): + result = nn_ops.gen_nn_ops.fractional_avg_pool( + value=np.zeros([3, 30, 30, 3]), + pooling_ratio=[1, -1, 3, 1], + pseudo_random=False, + overlapping=False, + deterministic=False, + seed=0, + seed2=0, + ) + self.evaluate(result) + class FractionalAvgPoolGradTest(test.TestCase): """Tests for FractionalAvgPoolGrad. 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 79b2c799d58..9102973fa13 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 @@ -320,7 +320,7 @@ class FractionalMaxPoolTest(test.TestCase): nn_ops.fractional_max_pool( rand_mat, [1, 1.5, 1.5, 1], seed=1, seed2=1, deterministic=True) - def testPoolingRatio(self): + def testPoolingRatioHasMoreDimThanInput(self): with self.cached_session() as _: with self.assertRaisesRegex( errors.InvalidArgumentError, @@ -338,6 +338,23 @@ class FractionalMaxPoolTest(test.TestCase): name=None) self.evaluate(result) + def testPoolingRatioValueOutOfRange(self): + with self.cached_session() as _: + # Whether turn on `TF2_BEHAVIOR` generates different error messages + with self.assertRaisesRegex( + (errors.InvalidArgumentError, ValueError), + r"(pooling_ratio cannot be smaller than 1, got: .*)|(is negative)"): + result = nn_ops.gen_nn_ops.fractional_max_pool( + value=np.zeros([3, 30, 30, 3]), + pooling_ratio=[1, -1, 3, 1], + pseudo_random=False, + overlapping=False, + deterministic=False, + seed=0, + seed2=0, + ) + self.evaluate(result) + class FractionalMaxPoolGradTest(test.TestCase): """Tests for FractionalMaxPoolGrad. |