Skip to content

Commit

Permalink
Add exception handlers for stoll in jit/frontend/schema_type_parser.c…
Browse files Browse the repository at this point in the history
…pp (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
  • Loading branch information
m4drat authored and pytorchmergebot committed Feb 10, 2023
1 parent d21a7e7 commit a1d210d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 8 deletions.
39 changes: 34 additions & 5 deletions torch/csrc/jit/frontend/schema_type_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,14 @@ c10::optional<c10::Device> SchemaTypeParser::tryToParseDeviceType() {
const std::string& num = L.expect(TK_NUMBER).text();
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
std::string::size_type num_len;
device_idx = c10::stoi(num, &num_len);
try {
device_idx = c10::stoi(num, &num_len);
} catch (const std::invalid_argument& e) {
throw ErrorReport(L.cur())
<< "Device index cannot be converted to integer";
} catch (const std::out_of_range& e) {
throw ErrorReport(L.cur()) << "Device index is too long";
}
}
if (dev == "cuda") {
return c10::Device(at::kCUDA, device_idx);
Expand All @@ -192,7 +199,15 @@ c10::optional<bool> SchemaTypeParser::tryToParseRequiresGrad() {
const std::string& num = L.expect(TK_NUMBER).text();
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
std::string::size_type num_len;
return (bool)c10::stoi(num, &num_len);

try {
return (bool)c10::stoi(num, &num_len);
} catch (const std::invalid_argument& e) {
throw ErrorReport(L.cur())
<< "Field requires_grad cannot be converted to integer";
} catch (const std::out_of_range& e) {
throw ErrorReport(L.cur()) << "Field requires_grad is too long";
}
}

TypePtr SchemaTypeParser::parseRefinedTensor() {
Expand Down Expand Up @@ -245,8 +260,15 @@ TypePtr SchemaTypeParser::parseRefinedTensor() {
const std::string& num = L.expect(TK_NUMBER).text();
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
std::string::size_type num_len;
auto stride = c10::stoll(num, &num_len);
strides.push_back(stride);
try {
auto stride = c10::stoll(num, &num_len);
strides.push_back(stride);
} catch (const std::invalid_argument& e) {
throw ErrorReport(L.cur())
<< "The stride value cannot be converted to int";
} catch (const std::out_of_range& e) {
throw ErrorReport(L.cur()) << "The stride is too big";
}
});
return;
}
Expand Down Expand Up @@ -277,7 +299,14 @@ TypePtr SchemaTypeParser::parseRefinedTensor() {
const std::string& num = L.expect(TK_NUMBER).text();
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
std::string::size_type num_len;
int64_t dim = c10::stoll(num, &num_len);
int64_t dim = 0;
try {
dim = c10::stoll(num, &num_len);
} catch (const std::invalid_argument& e) {
throw ErrorReport(L.cur()) << "The number can't be converted to int";
} catch (const std::out_of_range& e) {
throw ErrorReport(L.cur()) << "Number is too big";
}
if (shape_symbol) {
L.expect(')');
dim = -dim;
Expand Down
30 changes: 27 additions & 3 deletions torch/csrc/jit/ir/irparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,40 @@ ParsedLiteral IRParser::parseScalarLiteral(Node* n) {
str += L.cur().text();
if (str.find('j') != std::string::npos) {
r.k = AttributeKind::c;
auto imag = c10::stod(str.substr(0, str.size() - 1));
double imag = 0.0f;
try {
imag = c10::stod(str.substr(0, str.size() - 1));
} catch (const std::invalid_argument& e) {
throw ErrorReport(token.range)
<< "Number cannot be converted to double";
} catch (const std::out_of_range& e) {
throw ErrorReport(token.range)
<< "Number is too long to be represented in type double";
}
r.c = c10::complex<double>(0, imag);
} else if (
str.find('.') != std::string::npos ||
str.find('e') != std::string::npos) {
r.k = AttributeKind::f;
r.f = c10::stod(str);
try {
r.f = c10::stod(str);
} catch (const std::invalid_argument& e) {
throw ErrorReport(token.range)
<< "Number cannot be converted to double";
} catch (const std::out_of_range& e) {
throw ErrorReport(token.range)
<< "Number is too long to be represented in type double";
}
} else {
r.k = AttributeKind::i;
r.i = c10::stoll(str);
try {
r.i = c10::stoll(str);
} catch (const std::invalid_argument& e) {
throw ErrorReport(token.range)
<< "Number cannot be converted to integer";
} catch (const std::out_of_range& e) {
throw ErrorReport(token.range) << "Number is too big";
}
}
L.next();
return r;
Expand Down

0 comments on commit a1d210d

Please sign in to comment.