aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Unique TensorFlower <gardener@tensorflow.org>2022-10-24 14:30:10 -0700
committerTensorFlow Release Automation <jenkins@tensorflow.org>2022-11-14 22:34:45 +0000
commitea08e8b7f49641cfb7080759b051dd77a8c69274 (patch)
treebe4d475b5b3865470c85e4016c8c3d2bdaa4e0d7
parentf52e0aefe44b643b9cf3474834ab9bbb59c7e7dc (diff)
downloadtensorflow-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.cc14
-rw-r--r--tensorflow/core/kernels/fractional_max_pool_op.cc6
-rw-r--r--tensorflow/core/ops/nn_ops.cc7
-rw-r--r--tensorflow/core/ops/nn_ops_test.cc13
-rw-r--r--tensorflow/python/kernel_tests/nn_ops/fractional_avg_pool_op_test.py35
-rw-r--r--tensorflow/python/kernel_tests/nn_ops/fractional_max_pool_op_test.py19
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.