Skip to content

Commit a1d210d

Browse files
m4dratpytorchmergebot
authored andcommitted
Add exception handlers for stoll in jit/frontend/schema_type_parser.cpp (pytorch#94295)
Hi! I've been fuzzing different pytorch modules, and found a few crashes. Specifically, I'm talking about `schema_type_parser.cpp` and `irparser.cpp`. Inside these files, different standard conversion functions are used (such as `stoll`, `stoi`, `stod`, `stoull`). However, default `std` exceptions, such as `std::out_of_range`, `std::invalid_argument`, are not handled. Some of the crash-files: 1. [crash-493db74c3426e79b2bf0ffa75bb924503cb9acdc.zip](https://github.com/pytorch/pytorch/files/10237616/crash-493db74c3426e79b2bf0ffa75bb924503cb9acdc.zip) - crash source: schema_type_parser.cpp:272 2. [crash-67bb5d34ca48235687cc056e2cdeb2476b8f4aa5.zip](https://github.com/pytorch/pytorch/files/10237618/crash-67bb5d34ca48235687cc056e2cdeb2476b8f4aa5.zip) - crash source: schema_type_parser.cpp:240 3. [crash-0157bca5c41bffe112aa01f3b0f2099ca4bcc62f.zip](https://github.com/pytorch/pytorch/files/10307970/crash-0157bca5c41bffe112aa01f3b0f2099ca4bcc62f.zip) - crash source: schema_type_parser.cpp:179 4. [crash-430da923e56adb9569362efa7fa779921371b710.zip](https://github.com/pytorch/pytorch/files/10307972/crash-430da923e56adb9569362efa7fa779921371b710.zip) - crash source: schema_type_parser.cpp:196 The provided patch adds exception handlers for `std::invalid_argument` and `std::out_of_range`, to rethrow these exceptions with `ErrorReport`. ### How to reproduce 1. To reproduce the crash, use provided docker: [Dockerfile](https://github.com/ispras/oss-sydr-fuzz/blob/master/projects/pytorch/Dockerfile) 2. Build the container: `docker build -t oss-sydr-fuzz-pytorch-reproduce .` 3. Copy crash file to the current directory 5. Run the container: ``docker run --privileged --network host -v `pwd`:/homedir --rm -it oss-sydr-fuzz-pytorch-reproduce /bin/bash`` 6. And execute the binary: `/irparser_fuzz /homedir/crash-67bb5d34ca48235687cc056e2cdeb2476b8f4aa5` After execution completes you will see this error message: ```txt terminate called after throwing an instance of 'std::out_of_range' what(): stoll ``` And this stacktrace: ```asan ==9626== ERROR: libFuzzer: deadly signal #0 0x5b4cf1 in __sanitizer_print_stack_trace /llvm-project/compiler-rt/lib/asan/asan_stack.cpp:87:3 #1 0x529627 in fuzzer::PrintStackTrace() /llvm-project/compiler-rt/lib/fuzzer/FuzzerUtil.cpp:210:5 #2 0x50f833 in fuzzer::Fuzzer::CrashCallback() /llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:233:3 #3 0x7ffff7c3741f (/lib/x86_64-linux-gnu/libpthread.so.0+0x1441f) #4 0x7ffff7a5700a in raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300a) #5 0x7ffff7a36858 in abort (/lib/x86_64-linux-gnu/libc.so.6+0x22858) #6 0x7ffff7e74910 (/lib/x86_64-linux-gnu/libstdc++.so.6+0x9e910) #7 0x7ffff7e8038b (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa38b) #8 0x7ffff7e803f6 in std::terminate() (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa3f6) #9 0x7ffff7e806a8 in __cxa_throw (/lib/x86_64-linux-gnu/libstdc++.so.6+0xaa6a8) #10 0x7ffff7e7737d in std::__throw_out_of_range(char const*) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa137d) #11 0xbd0579 in long long __gnu_cxx::__stoa<long long, long long, char, int>(long long (*)(char const*, char**, int), char const*, char const*, unsigned long*, int) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/ext/string_conversions.h:86:2 #12 0xc10f9c in std::__cxx11::stoll(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long*, int) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/basic_string.h:6572:12 #13 0xc10f9c in torch::jit::SchemaTypeParser::parseRefinedTensor()::$_2::operator()() const::'lambda'()::operator()() const /pytorch_fuzz/torch/csrc/jit/frontend/schema_type_parser.cpp:240:25 #14 0xc10f9c in void c10::function_ref<void ()>::callback_fn<torch::jit::SchemaTypeParser::parseRefinedTensor()::$_2::operator()() const::'lambda'()>(long) /pytorch_fuzz/c10/util/FunctionRef.h:43:12 #15 0xbfbb27 in torch::jit::SchemaTypeParser::parseList(int, int, int, c10::function_ref<void ()>) /pytorch_fuzz/torch/csrc/jit/frontend/schema_type_parser.cpp:424:7 #16 0xc0ef24 in torch::jit::SchemaTypeParser::parseRefinedTensor()::$_2::operator()() const /pytorch_fuzz/torch/csrc/jit/frontend/schema_type_parser.cpp:236:9 #17 0xc0ef24 in void c10::function_ref<void ()>::callback_fn<torch::jit::SchemaTypeParser::parseRefinedTensor()::$_2>(long) /pytorch_fuzz/c10/util/FunctionRef.h:43:12 #18 0xbfbb27 in torch::jit::SchemaTypeParser::parseList(int, int, int, c10::function_ref<void ()>) /pytorch_fuzz/torch/csrc/jit/frontend/schema_type_parser.cpp:424:7 #19 0xbff590 in torch::jit::SchemaTypeParser::parseRefinedTensor() /pytorch_fuzz/torch/csrc/jit/frontend/schema_type_parser.cpp:209:3 #20 0xc02992 in torch::jit::SchemaTypeParser::parseType() /pytorch_fuzz/torch/csrc/jit/frontend/schema_type_parser.cpp:362:13 #21 0x9445642 in torch::jit::IRParser::parseVarWithType(bool) /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:111:35 #22 0x944ff4c in torch::jit::IRParser::parseOperatorOutputs(std::vector<torch::jit::VarWithType, std::allocator<torch::jit::VarWithType> >*)::$_0::operator()() const /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:138:21 #23 0x944ff4c in void std::__invoke_impl<void, torch::jit::IRParser::parseOperatorOutputs(std::vector<torch::jit::VarWithType, std::allocator<torch::jit::VarWithType> >*)::$_0&>(std::__invoke_other, torch::jit::IRParser::parseOperatorOutputs(std::vector<torch::jit::VarWithType, std::allocator<torch::jit::VarWithType> >*)::$_0&) /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h:60:14 #24 0x94463a7 in torch::jit::IRParser::parseList(int, int, int, std::function<void ()> const&) /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:498:7 #25 0x94460a5 in torch::jit::IRParser::parseOperatorOutputs(std::vector<torch::jit::VarWithType, std::allocator<torch::jit::VarWithType> >*) /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:137:3 #26 0x944c1ce in torch::jit::IRParser::parseOperator(torch::jit::Block*) /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:384:3 #27 0x944bf56 in torch::jit::IRParser::parseOperatorsList(torch::jit::Block*) /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:362:5 #28 0x9444f5f in torch::jit::IRParser::parse() /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:482:3 #29 0x94448df in torch::jit::parseIR(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, torch::jit::Graph*, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, torch::jit::Value*, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, torch::jit::Value*> > >&) /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:94:5 #30 0x944526e in torch::jit::parseIR(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, torch::jit::Graph*) /pytorch_fuzz/torch/csrc/jit/ir/irparser.cpp:99:3 #31 0x5e3ebd in LLVMFuzzerTestOneInput /irparser_fuzz.cc:43:5 #32 0x510d61 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #33 0x4fac7c in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6 #34 0x5009cb in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:860:9 #35 0x529f62 in main /llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #36 0x7ffff7a38082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) #37 0x4f559d in _start (/irparser_fuzz+0x4f559d) ``` Following these steps with the remaining crashes will give you almost the same results. Pull Request resolved: pytorch#94295 Approved by: https://github.com/davidberard98
1 parent d21a7e7 commit a1d210d

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

torch/csrc/jit/frontend/schema_type_parser.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,14 @@ c10::optional<c10::Device> SchemaTypeParser::tryToParseDeviceType() {
175175
const std::string& num = L.expect(TK_NUMBER).text();
176176
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
177177
std::string::size_type num_len;
178-
device_idx = c10::stoi(num, &num_len);
178+
try {
179+
device_idx = c10::stoi(num, &num_len);
180+
} catch (const std::invalid_argument& e) {
181+
throw ErrorReport(L.cur())
182+
<< "Device index cannot be converted to integer";
183+
} catch (const std::out_of_range& e) {
184+
throw ErrorReport(L.cur()) << "Device index is too long";
185+
}
179186
}
180187
if (dev == "cuda") {
181188
return c10::Device(at::kCUDA, device_idx);
@@ -192,7 +199,15 @@ c10::optional<bool> SchemaTypeParser::tryToParseRequiresGrad() {
192199
const std::string& num = L.expect(TK_NUMBER).text();
193200
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
194201
std::string::size_type num_len;
195-
return (bool)c10::stoi(num, &num_len);
202+
203+
try {
204+
return (bool)c10::stoi(num, &num_len);
205+
} catch (const std::invalid_argument& e) {
206+
throw ErrorReport(L.cur())
207+
<< "Field requires_grad cannot be converted to integer";
208+
} catch (const std::out_of_range& e) {
209+
throw ErrorReport(L.cur()) << "Field requires_grad is too long";
210+
}
196211
}
197212

198213
TypePtr SchemaTypeParser::parseRefinedTensor() {
@@ -245,8 +260,15 @@ TypePtr SchemaTypeParser::parseRefinedTensor() {
245260
const std::string& num = L.expect(TK_NUMBER).text();
246261
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
247262
std::string::size_type num_len;
248-
auto stride = c10::stoll(num, &num_len);
249-
strides.push_back(stride);
263+
try {
264+
auto stride = c10::stoll(num, &num_len);
265+
strides.push_back(stride);
266+
} catch (const std::invalid_argument& e) {
267+
throw ErrorReport(L.cur())
268+
<< "The stride value cannot be converted to int";
269+
} catch (const std::out_of_range& e) {
270+
throw ErrorReport(L.cur()) << "The stride is too big";
271+
}
250272
});
251273
return;
252274
}
@@ -277,7 +299,14 @@ TypePtr SchemaTypeParser::parseRefinedTensor() {
277299
const std::string& num = L.expect(TK_NUMBER).text();
278300
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
279301
std::string::size_type num_len;
280-
int64_t dim = c10::stoll(num, &num_len);
302+
int64_t dim = 0;
303+
try {
304+
dim = c10::stoll(num, &num_len);
305+
} catch (const std::invalid_argument& e) {
306+
throw ErrorReport(L.cur()) << "The number can't be converted to int";
307+
} catch (const std::out_of_range& e) {
308+
throw ErrorReport(L.cur()) << "Number is too big";
309+
}
281310
if (shape_symbol) {
282311
L.expect(')');
283312
dim = -dim;

torch/csrc/jit/ir/irparser.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,16 +189,40 @@ ParsedLiteral IRParser::parseScalarLiteral(Node* n) {
189189
str += L.cur().text();
190190
if (str.find('j') != std::string::npos) {
191191
r.k = AttributeKind::c;
192-
auto imag = c10::stod(str.substr(0, str.size() - 1));
192+
double imag = 0.0f;
193+
try {
194+
imag = c10::stod(str.substr(0, str.size() - 1));
195+
} catch (const std::invalid_argument& e) {
196+
throw ErrorReport(token.range)
197+
<< "Number cannot be converted to double";
198+
} catch (const std::out_of_range& e) {
199+
throw ErrorReport(token.range)
200+
<< "Number is too long to be represented in type double";
201+
}
193202
r.c = c10::complex<double>(0, imag);
194203
} else if (
195204
str.find('.') != std::string::npos ||
196205
str.find('e') != std::string::npos) {
197206
r.k = AttributeKind::f;
198-
r.f = c10::stod(str);
207+
try {
208+
r.f = c10::stod(str);
209+
} catch (const std::invalid_argument& e) {
210+
throw ErrorReport(token.range)
211+
<< "Number cannot be converted to double";
212+
} catch (const std::out_of_range& e) {
213+
throw ErrorReport(token.range)
214+
<< "Number is too long to be represented in type double";
215+
}
199216
} else {
200217
r.k = AttributeKind::i;
201-
r.i = c10::stoll(str);
218+
try {
219+
r.i = c10::stoll(str);
220+
} catch (const std::invalid_argument& e) {
221+
throw ErrorReport(token.range)
222+
<< "Number cannot be converted to integer";
223+
} catch (const std::out_of_range& e) {
224+
throw ErrorReport(token.range) << "Number is too big";
225+
}
202226
}
203227
L.next();
204228
return r;

0 commit comments

Comments
 (0)