Skip to content

Commit 9763d0a

Browse files
tensorflower-gardenernluehr
authored andcommitted
Fix security vulnerability with FractionalMax(AVG)Pool with illegal pooling_ratio PiperOrigin-RevId: 483486453
1 parent 9077294 commit 9763d0a

7 files changed

+90
-6
lines changed

RELEASE.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Release 1.15.5+nv22.12
2+
## Bug fixes and Other Changes
3+
* Fixes OOB access in FractionalMaxPool and FractionalAVGPool.
4+
([CVE-2022-41900](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-41900)).
5+
6+
17
# Release 1.15.5+nv22.06
28
## Bug Fixes and Other Changes
39
* Fixes OOB read in TfLite Gather_Nd.

tensorflow/core/kernels/fractional_avg_pool_op.cc

+12
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class FractionalAvgPoolOp : public OpKernel {
4343
OP_REQUIRES(context, pooling_ratio_.size() == 4,
4444
errors::InvalidArgument(
4545
"pooling_ratio field must specify 4 dimensions"));
46+
for (std::size_t i = 0; i < pooling_ratio_.size(); ++i) {
47+
OP_REQUIRES(context, pooling_ratio_[i] >= 1,
48+
errors::InvalidArgument(
49+
"pooling_ratio cannot be smaller than 1, got: ",
50+
pooling_ratio_[i]));
51+
}
4652
OP_REQUIRES(
4753
context, pooling_ratio_[0] == 1 || pooling_ratio_[3] == 1,
4854
errors::Unimplemented("Fractional average pooling is not yet "
@@ -80,6 +86,12 @@ class FractionalAvgPoolOp : public OpKernel {
8086
std::vector<int> output_size(tensor_in_and_out_dims);
8187
for (int i = 0; i < tensor_in_and_out_dims; ++i) {
8288
input_size[i] = tensor_in.dim_size(i);
89+
OP_REQUIRES(
90+
context, input_size[i] >= pooling_ratio_[i],
91+
errors::InvalidArgument("Pooling ratio is higher than input "
92+
"dimension size for dimension ",
93+
i, ". Input dim size: ", input_size[i],
94+
" pooling ratio: ", pooling_ratio_[i]));
8395
}
8496
// Output size.
8597
for (int i = 0; i < tensor_in_and_out_dims; ++i) {

tensorflow/core/kernels/fractional_max_pool_op.cc

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ class FractionalMaxPoolOp : public OpKernel {
4444
OP_REQUIRES(context, pooling_ratio_.size() == 4,
4545
errors::InvalidArgument("pooling_ratio field must "
4646
"specify 4 dimensions"));
47+
for (std::size_t i = 0; i < pooling_ratio_.size(); ++i) {
48+
OP_REQUIRES(context, pooling_ratio_[i] >= 1,
49+
errors::InvalidArgument(
50+
"pooling_ratio cannot be smaller than 1, got: ",
51+
pooling_ratio_[i]));
52+
}
4753

4854
OP_REQUIRES(
4955
context, pooling_ratio_[0] == 1 || pooling_ratio_[3] == 1,

tensorflow/core/ops/nn_ops.cc

+7
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ Status FractionalPoolShapeFn(InferenceContext* c) {
5757
}
5858
}
5959

60+
for (std::size_t i = 0; i < pooling_ratio.size(); ++i) {
61+
if (pooling_ratio[i] < 1) {
62+
return errors::InvalidArgument(
63+
"pooling_ratio cannot be smaller than 1, got: ", pooling_ratio[i]);
64+
}
65+
}
66+
6067
c->set_output(0, c->MakeShape(output_dims));
6168
c->set_output(1, c->Vector(output_dims[1]));
6269
c->set_output(2, c->Vector(output_dims[2]));

tensorflow/core/ops/nn_ops_test.cc

+7-6
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,8 @@ TEST(NNOpsTest, FractionalPool_ShapeFn) {
488488
.Finalize(&op.node_def));
489489
};
490490

491-
set_op(std::vector<float>{2.0f, 1, 1 / 1.5f, 1 / 2.0f});
491+
// pooling_ratio must >= 1.0
492+
set_op(std::vector<float>{2.0f, 1, 1.5f, 4.0f});
492493

493494
// Rank check.
494495
INFER_ERROR("must be rank 4", op, "[?,?,?]");
@@ -497,11 +498,11 @@ TEST(NNOpsTest, FractionalPool_ShapeFn) {
497498
INFER_OK(op, "?", "[?,?,?,?];[?];[?]");
498499
INFER_OK(op, "[?,?,?,?]", "[?,?,?,?];[?];[?]");
499500

500-
INFER_OK(op, "[10,20,30,40]", "[5,20,45,80];[20];[45]");
501-
INFER_OK(op, "[?,20,30,40]", "[?,20,45,80];[20];[45]");
502-
INFER_OK(op, "[10,?,30,40]", "[5,?,45,80];[?];[45]");
503-
INFER_OK(op, "[10,20,?,40]", "[5,20,?,80];[20];[?]");
504-
INFER_OK(op, "[10,20,30,?]", "[5,20,45,?];[20];[45]");
501+
INFER_OK(op, "[10,20,30,40]", "[5,20,20,10];[20];[20]");
502+
INFER_OK(op, "[?,20,30,40]", "[?,20,20,10];[20];[20]");
503+
INFER_OK(op, "[10,?,30,40]", "[5,?,20,10];[?];[20]");
504+
INFER_OK(op, "[10,20,?,40]", "[5,20,?,10];[20];[?]");
505+
INFER_OK(op, "[10,20,30,?]", "[5,20,20,?];[20];[20]");
505506

506507
// Wrong number of values for pooling_ratio.
507508
set_op(std::vector<float>{.5, 1.0, 1.5});

tensorflow/python/kernel_tests/fractional_avg_pool_op_test.py

+35
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,41 @@ def testNegativeSeqValuesForGradOp(self):
337337

338338
self.evaluate(z)
339339

340+
def testPoolingRatioHasMoreDimThanInput(self):
341+
with self.cached_session() as _:
342+
with self.assertRaisesRegex(
343+
errors.InvalidArgumentError,
344+
r"Pooling ratio is higher than input dimension size for dimension 1.*"
345+
):
346+
result = nn_ops.gen_nn_ops.fractional_avg_pool(
347+
value=constant_op.constant(
348+
value=[[[[1, 4, 2, 3]]]], dtype=dtypes.int64),
349+
pooling_ratio=[1.0, 1.44, 1.73, 1.0],
350+
pseudo_random=False,
351+
overlapping=False,
352+
deterministic=False,
353+
seed=0,
354+
seed2=0,
355+
name=None)
356+
self.evaluate(result)
357+
358+
def testPoolingRatioValueOutOfRange(self):
359+
with self.cached_session() as _:
360+
# Whether turn on `TF2_BEHAVIOR` generates different error messages
361+
with self.assertRaisesRegex(
362+
(errors.InvalidArgumentError, ValueError),
363+
r"(pooling_ratio cannot be smaller than 1, got: .*)|(is negative)"):
364+
result = nn_ops.gen_nn_ops.fractional_avg_pool(
365+
value=np.zeros([3, 30, 30, 3]),
366+
pooling_ratio=[1, -1, 3, 1],
367+
pseudo_random=False,
368+
overlapping=False,
369+
deterministic=False,
370+
seed=0,
371+
seed2=0,
372+
)
373+
self.evaluate(result)
374+
340375

341376
class FractionalAvgPoolGradTest(test.TestCase):
342377
"""Tests for FractionalAvgPoolGrad.

tensorflow/python/kernel_tests/fractional_max_pool_op_test.py

+17
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,23 @@ def testPoolingRatio(self):
326326
name=None)
327327
self.evaluate(result)
328328

329+
def testPoolingRatioValueOutOfRange(self):
330+
with self.cached_session() as _:
331+
# Whether turn on `TF2_BEHAVIOR` generates different error messages
332+
with self.assertRaisesRegex(
333+
(errors.InvalidArgumentError, ValueError),
334+
r"(pooling_ratio cannot be smaller than 1, got: .*)|(is negative)"):
335+
result = nn_ops.gen_nn_ops.fractional_max_pool(
336+
value=np.zeros([3, 30, 30, 3]),
337+
pooling_ratio=[1, -1, 3, 1],
338+
pseudo_random=False,
339+
overlapping=False,
340+
deterministic=False,
341+
seed=0,
342+
seed2=0,
343+
)
344+
self.evaluate(result)
345+
329346

330347
class FractionalMaxPoolGradTest(test.TestCase):
331348
"""Tests for FractionalMaxPoolGrad.

0 commit comments

Comments
 (0)