From 8fbd71f648b3250a098922172c083a859f5c09d6 Mon Sep 17 00:00:00 2001 From: Manuel Candales Date: Fri, 27 Jun 2025 07:28:00 -0700 Subject: [PATCH 1/2] [ET][Portable] Check scalar overflow: op_full Pull Request resolved: https://github.com/pytorch/executorch/pull/12014 ghstack-source-id: 293086873 @exported-using-ghexport Differential Revision: [D77386635](https://our.internmc.facebook.com/intern/diff/D77386635/) --- kernels/portable/cpu/op_full.cpp | 5 ++++- kernels/test/op_full_test.cpp | 27 +++++++++++++-------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/kernels/portable/cpu/op_full.cpp b/kernels/portable/cpu/op_full.cpp index 83ffcad45a6..b83637f2b91 100644 --- a/kernels/portable/cpu/op_full.cpp +++ b/kernels/portable/cpu/op_full.cpp @@ -37,7 +37,10 @@ Tensor& full_out( constexpr auto name = "full.out"; ET_SWITCH_REALHBBF16_TYPES(out_type, ctx, name, CTYPE_OUT, [&] { - CTYPE_OUT val_casted = utils::scalar_to(fill_value); + auto opt_val_casted = + utils::internal::check_overflow_scalar_cast(fill_value); + ET_KERNEL_CHECK(ctx, opt_val_casted.has_value(), InvalidArgument, ); + auto val_casted = opt_val_casted.value(); auto data_out = out.mutable_data_ptr(); for (const auto i : c10::irange(out.numel())) { data_out[i] = val_casted; diff --git a/kernels/test/op_full_test.cpp b/kernels/test/op_full_test.cpp index 93129679087..35115dc7ed6 100644 --- a/kernels/test/op_full_test.cpp +++ b/kernels/test/op_full_test.cpp @@ -7,6 +7,7 @@ */ #include // Declares the operator +#include #include #include #include @@ -59,6 +60,17 @@ class OpFullOutTest : public OperatorTest { op_full_out(aref, 1.0, out); EXPECT_TENSOR_EQ(out, tf.ones(size_int32_t)); } + + template + void expect_bad_scalar_value_dies(const Scalar& bad_value) { + TensorFactory tf; + std::vector sizes = {2, 2}; + std::vector sizes_int64_t(sizes.begin(), sizes.end()); + auto aref = IntArrayRef(sizes_int64_t.data(), sizes_int64_t.size()); + Tensor out = tf.zeros(sizes); + + ET_EXPECT_KERNEL_FAILURE(context_, op_full_out(aref, bad_value, out)); + } }; #define GENERATE_TEST(_, DTYPE) \ @@ -72,20 +84,7 @@ class OpFullOutTest : public OperatorTest { ET_FORALL_REALHBF16_TYPES(GENERATE_TEST) -TEST_F(OpFullOutTest, ValueOverflow) { - if (torch::executor::testing::SupportedFeatures::get()->is_aten) { - GTEST_SKIP() << "ATen kernel doesn't handle overflow"; - } - TensorFactory tf; - - std::vector sizes_int64_t_vec = {2, 3}; - std::vector sizes_in32_t_vec = {2, 3}; - auto sizes = IntArrayRef(sizes_int64_t_vec.data(), sizes_int64_t_vec.size()); - - Tensor out = tf.zeros(sizes_in32_t_vec); - - op_full_out(sizes, 1000, out); -} +GENERATE_SCALAR_OVERFLOW_TESTS(OpFullOutTest) TEST_F(OpFullOutTest, HalfSupport) { TensorFactory tf; From 1096366d1b09b73ec31ae17c0d5b0f062bb04d1b Mon Sep 17 00:00:00 2001 From: Manuel Candales Date: Fri, 27 Jun 2025 07:28:01 -0700 Subject: [PATCH 2/2] [ET][Portable] Check scalar overflow: op_full_like Pull Request resolved: https://github.com/pytorch/executorch/pull/12015 ghstack-source-id: 293086874 @exported-using-ghexport Differential Revision: [D77386637](https://our.internmc.facebook.com/intern/diff/D77386637/) --- kernels/portable/cpu/op_full_like.cpp | 22 +++++++++------------- kernels/test/op_full_like_test.cpp | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/kernels/portable/cpu/op_full_like.cpp b/kernels/portable/cpu/op_full_like.cpp index 7671cd61ea9..0e263fb9c10 100644 --- a/kernels/portable/cpu/op_full_like.cpp +++ b/kernels/portable/cpu/op_full_like.cpp @@ -48,23 +48,19 @@ Tensor& full_like_out( out, "Failed to resize output tensor."); - ScalarType val_type = utils::get_scalar_dtype(fill_value); ScalarType out_type = out.scalar_type(); constexpr auto name = "scalar_tensor.out"; - ET_SWITCH_REALB_TYPES(val_type, ctx, name, CTYPE_VAL, [&] { - CTYPE_VAL val; - ET_KERNEL_CHECK( - ctx, utils::extract_scalar(fill_value, &val), InvalidArgument, ); - - ET_SWITCH_REALHBBF16_TYPES(out_type, ctx, name, CTYPE_OUT, [&] { - CTYPE_OUT val_casted = static_cast(val); - auto data_out = out.mutable_data_ptr(); - for (const auto i : c10::irange(out.numel())) { - data_out[i] = val_casted; - } - }); + ET_SWITCH_REALHBBF16_TYPES(out_type, ctx, name, CTYPE_OUT, [&] { + auto opt_val_casted = + utils::internal::check_overflow_scalar_cast(fill_value); + ET_KERNEL_CHECK(ctx, opt_val_casted.has_value(), InvalidArgument, ); + auto val_casted = opt_val_casted.value(); + auto data_out = out.mutable_data_ptr(); + for (const auto i : c10::irange(out.numel())) { + data_out[i] = val_casted; + } }); return out; diff --git a/kernels/test/op_full_like_test.cpp b/kernels/test/op_full_like_test.cpp index c0b9dcc4107..6e7692f5347 100644 --- a/kernels/test/op_full_like_test.cpp +++ b/kernels/test/op_full_like_test.cpp @@ -7,6 +7,7 @@ */ #include // Declares the operator +#include #include #include #include @@ -65,6 +66,18 @@ class OpFullLikeTest : public OperatorTest { ET_EXPECT_KERNEL_FAILURE( context_, op_full_like_out(in, value, memory_format, out)); } + + template + void expect_bad_scalar_value_dies(const Scalar& bad_value) { + TensorFactory tf; + const std::vector sizes = {2, 2}; + Tensor in = tf.zeros(sizes); + Tensor out = tf.zeros(sizes); + optional memory_format; + + ET_EXPECT_KERNEL_FAILURE( + context_, op_full_like_out(in, bad_value, memory_format, out)); + } }; template <> @@ -209,3 +222,5 @@ TEST_F(OpFullLikeTest, HalfSupport) { op_full_like_out(in, INFINITY, memory_format, out); EXPECT_TENSOR_CLOSE(out, tf.full({2, 3}, INFINITY)); } + +GENERATE_SCALAR_OVERFLOW_TESTS(OpFullLikeTest)