Skip to content

Commit dc726f9

Browse files
swolchokfacebook-github-bot
authored andcommitted
Fix stack buffer overflow when XNNPACK tensor has too many dims (#3233)
Summary: Pull Request resolved: #3233 Noticed this overflow when I was looking through the XNNPACK backend. I am not very familiar with executorch or XNNPACK, so please be critical in review! In particular, my test is crashing in xnn_delete_runtime and I don't know why; it was previously getting a UBSAN failure for the stack buffer overflow before I patched XNNExecutor.cpp Reviewed By: digantdesai, mcr229 Differential Revision: D56450593 fbshipit-source-id: d0f2b4d5dc44e08f9679560d4a6adde7f1559173
1 parent e5471a5 commit dc726f9

File tree

4 files changed

+115
-1
lines changed

4 files changed

+115
-1
lines changed

backends/xnnpack/runtime/XNNExecutor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ __ET_NODISCARD Error XNNExecutor::prepare_args(EValue** args) {
8787
if (i < input_ids_.size()) {
8888
size_t num_dims = tensor->dim();
8989
size_t dims[XNN_MAX_TENSOR_DIMS];
90+
ET_CHECK_OR_RETURN_ERROR(
91+
num_dims <= XNN_MAX_TENSOR_DIMS,
92+
InvalidArgument,
93+
"XNNPACK backend accepts tensors with at most %d dims, but got %zu",
94+
XNN_MAX_TENSOR_DIMS,
95+
num_dims);
9096
for (int d = 0; d < num_dims; ++d) {
9197
dims[d] = tensor->size(d);
9298
}

backends/xnnpack/targets.bzl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ def define_common_targets():
3838
preprocessor_flags = [
3939
# "-DENABLE_XNNPACK_PROFILING",
4040
],
41+
exported_deps = [
42+
"//executorch/runtime/backend:interface",
43+
],
4144
deps = [
4245
third_party_dep("XNNPACK"),
43-
"//executorch/runtime/backend:interface",
4446
"//executorch/backends/xnnpack/serialization:xnnpack_flatbuffer_header",
4547
"//executorch/backends/xnnpack/threadpool:threadpool",
4648
"//executorch/runtime/core/exec_aten/util:tensor_util",
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#include <executorch/backends/xnnpack/runtime/XNNExecutor.h>
10+
#include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
11+
#include <gtest/gtest.h>
12+
#include <xnnpack/subgraph.h>
13+
14+
using torch::executor::Error;
15+
using torch::executor::EValue;
16+
using torch::executor::testing::TensorFactory;
17+
using torch::executor::xnnpack::delegate::XNNExecutor;
18+
19+
TEST(XNNExecutorTest, ArgumentWithTooManyDimensions) {
20+
XNNExecutor executor;
21+
xnn_subgraph_t subgraph = nullptr;
22+
xnn_runtime_t rt = nullptr;
23+
et_pal_init();
24+
ASSERT_EQ(xnn_initialize(nullptr), xnn_status_success);
25+
ASSERT_EQ(xnn_create_subgraph(2, 0, &subgraph), xnn_status_success);
26+
std::unique_ptr<xnn_subgraph, decltype(&xnn_delete_subgraph)> auto_subgraph(
27+
subgraph, xnn_delete_subgraph);
28+
29+
auto input_id = XNN_INVALID_NODE_ID;
30+
std::vector<size_t> dims = {
31+
1,
32+
};
33+
ASSERT_EQ(
34+
xnn_status_success,
35+
xnn_define_quantized_tensor_value(
36+
subgraph,
37+
xnn_datatype_qint8,
38+
0,
39+
1,
40+
dims.size(),
41+
dims.data(),
42+
nullptr,
43+
/*external_id=*/0,
44+
/*flags=*/XNN_VALUE_FLAG_EXTERNAL_INPUT,
45+
&input_id));
46+
ASSERT_NE(input_id, XNN_INVALID_NODE_ID);
47+
48+
auto output_id = XNN_INVALID_NODE_ID;
49+
ASSERT_EQ(
50+
xnn_status_success,
51+
xnn_define_quantized_tensor_value(
52+
subgraph,
53+
xnn_datatype_qint8,
54+
0,
55+
1,
56+
dims.size(),
57+
dims.data(),
58+
nullptr,
59+
/*external_id=*/0,
60+
/*flags=*/XNN_VALUE_FLAG_EXTERNAL_OUTPUT,
61+
&output_id));
62+
ASSERT_NE(output_id, XNN_INVALID_NODE_ID);
63+
64+
ASSERT_EQ(
65+
xnn_status_success,
66+
xnn_define_clamp(subgraph, 1, 2, input_id, output_id, 0));
67+
68+
ASSERT_EQ(xnn_create_runtime(subgraph, &rt), xnn_status_success);
69+
EXPECT_EQ(
70+
executor.initialize(
71+
rt,
72+
{
73+
0,
74+
},
75+
{
76+
1,
77+
}),
78+
Error::Ok);
79+
TensorFactory<exec_aten::ScalarType::Int> tf;
80+
auto input_tensor = tf.make({1, 1, 1, 1, 1, 1, 1, 1, 1}, {42});
81+
ASSERT_EQ(input_tensor.dim(), 9);
82+
auto output_tensor = tf.make(
83+
{
84+
1,
85+
},
86+
{
87+
1,
88+
});
89+
EValue input_ev(input_tensor);
90+
EValue output_ev(output_tensor);
91+
std::array<EValue*, 2> args = {&input_ev, &output_ev};
92+
// Check for invalid number of dimensions should fail without stack overflow.
93+
EXPECT_EQ(executor.prepare_args(args.data()), Error::InvalidArgument);
94+
}

backends/xnnpack/test/targets.bzl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
load("@fbsource//xplat/executorch/backends/xnnpack/third-party:third_party_libs.bzl", "third_party_dep")
12
load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "runtime")
23

34
def define_common_targets():
@@ -17,3 +18,14 @@ def define_common_targets():
1718
"//executorch/backends/xnnpack:dynamic_quant_utils",
1819
],
1920
)
21+
22+
runtime.cxx_test(
23+
name = "xnnexecutor_test",
24+
srcs = ["runtime/test_xnnexecutor.cpp"],
25+
deps = [
26+
third_party_dep("XNNPACK"),
27+
"//executorch/runtime/core/exec_aten/testing_util:tensor_util",
28+
"//executorch/runtime/core/exec_aten/util:scalar_type_util",
29+
"//executorch/backends/xnnpack:xnnpack_backend",
30+
],
31+
)

0 commit comments

Comments
 (0)