Repository: google/clusterfuzz

Issue:
golang: Different bugs for same stack trace
It looks like the parsing of the stack trace is not so good 

cf
https://oss-fuzz.com/testcase-detail/5194651375108096
```
goroutine 17 [running, locked to thread]:
--
  | regexp.(*Regexp).Split(0x10c0000b2640, {0x10c000ac201f, 0x962c00}, 0xffffffffffffffff)
  | regexp/regexp.go:1266 +0x617
  | github.com/google/gonids.(*Rule).option(0x10c000066000, {0x0, {0x10c000ac2016, 0x10c000044000}}, 0x10c0001dc000)
  | github.com/google/gonids/parser.go:675 +0x36c5
  | github.com/google/gonids.parseRuleAux({0x10c000ac2000, 0x37a78}, 0x0)
  | github.com/google/gonids/parser.go:942 +0x6b3
  | github.com/google/gonids.ParseRule(...)
  | github.com/google/gonids/parser.go:971
  | github.com/google/gonids.FuzzParseRule({0x7f369cb75800, 0x0, 0x10c000000601})
  | github.com/google/gonids/fuzz.go:20 +0x54
  | main.LLVMFuzzerTestOneInput(...)
  | ./main.3953748960.go:21
```

Only the line `github.com/google/gonids.ParseRule(...)`is in red, recognized as a stack trace line if I understand correctly

vs
https://oss-fuzz.com/testcase-detail/5115516607397888
```
	
goroutine 17 [running, locked to thread]:
regexp.(*Regexp).Split(0x10c0000b6640, 0x10c000176a9f, 0x774bc0, 0xffffffffffffffff)
 regexp/regexp.go:1266 +0x61c
github.com/google/gonids.(*Rule).option(0x10c000084600, 0x1010000000050, 0x10c000176a96, 0x0, 0x7fb715876778)
 github.com/google/gonids/parser.go:675 +0x3705
github.com/google/gonids.parseRuleAux(0x10c000176a80, 0x62b0000cb200, 0x6600)
 github.com/google/gonids/parser.go:943 +0x6ce
github.com/google/gonids.ParseRule(...)
 github.com/google/gonids/parser.go:972
github.com/google/gonids.FuzzParseRule(0x62b0000cb200, 0x0, 0x1)
 github.com/google/gonids/fuzz.go:20 +0x54
main.LLVMFuzzerTestOneInput(...)
 ./main.834012382.go:21
AddressSanitizer:DEADLYSIGNAL
```

where 
```
regexp.(*Regexp).Split(0x10c0000b6640, 0x10c000176a9f, 0x774bc0, 0xffffffffffffffff)
github.com/google/gonids.(*Rule).option(0x10c000084600, 0x1010000000050, 0x10c000176a96, 0x0, 0x7fb715876778)
github.com/google/gonids.parseRuleAux(0x10c000176a80, 0x62b0000cb200, 0x6600)
```
are in red

cf https://github.com/golang/go/issues/49075
The changes in the stack trace format seems to come from https://github.com/golang/go/issues/49075

@oliverchang are you the one who knows about this stack trace parsing ?


Discussion:
I think this is `GOLANG_STACK_FRAME_FUNCTION_REGEX` definition https://github.com/google/clusterfuzz/blob/08f52cd1b9c304cf39988561f1241cee9fd5673a/src/clusterfuzz/stacktraces/constants.py#L308 that needs to be extended to include `{}`
I'll take a look tomorrow. 

Resolving patch:
diff --git a/src/clusterfuzz/stacktraces/constants.py b/src/clusterfuzz/stacktraces/constants.py
--- a/src/clusterfuzz/stacktraces/constants.py
+++ b/src/clusterfuzz/stacktraces/constants.py
@@ -157,6 +157,7 @@
     r'Sanitizer: calloc-overflow',
     r'Sanitizer: calloc parameters overflow',
     r'Sanitizer: requested allocation size.*exceeds maximum supported size',
+    r'Sanitizer: out of memory',
     r'TerminateBecauseOutOfMemory',
     r'allocator is out of memory trying to allocate',
     r'blinkGCOutOfMemory',
@@ -306,7 +307,7 @@
 GOLANG_FATAL_ERROR_REGEX = re.compile(r'^fatal error: (.*)')
 
 GOLANG_STACK_FRAME_FUNCTION_REGEX = re.compile(
-    r'^([0-9a-zA-Z\.\-\_\\\/\(\)\*]+)\([x0-9a-f\s,\.]*\)$')
+    r'^([0-9a-zA-Z\.\-\_\\\/\(\)\*]+)\([x0-9a-f\s,\.{}]*\)$')
 
 # Python specific regular expressions.
 PYTHON_UNHANDLED_EXCEPTION = re.compile(


Test patch:
diff --git a/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_data/go_braces.txt b/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_data/go_braces.txt
new file mode 100644
--- /dev/null
+++ b/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_data/go_braces.txt
@@ -0,0 +1,22 @@
+panic: runtime error: slice bounds out of range [699494522:64250]
+goroutine 17 [running, locked to thread]:
+regexp.(*Regexp).Split(0x10c0000b2640, {0x10c000ac201f, 0x962c00}, 0xffffffffffffffff)
+ regexp/regexp.go:1266 +0x617
+github.com/google/gonids.(*Rule).option(0x10c000066000, {0x0, {0x10c000ac2016, 0x10c000044000}}, 0x10c0001dc000)
+ github.com/google/gonids/parser.go:675 +0x36c5
+github.com/google/gonids.parseRuleAux({0x10c000ac2000, 0x37a78}, 0x0)
+ github.com/google/gonids/parser.go:942 +0x6b3
+github.com/google/gonids.ParseRule(...)
+ github.com/google/gonids/parser.go:971
+github.com/google/gonids.FuzzParseRule({0x7f369cb75800, 0x0, 0x10c000000601})
+ github.com/google/gonids/fuzz.go:20 +0x54
+main.LLVMFuzzerTestOneInput(...)
+ ./main.3953748960.go:21
+AddressSanitizer:DEADLYSIGNAL
+=================================================================
+==16820==ERROR: AddressSanitizer: ABRT on unknown address 0x0539000041b4 (pc 0x0000005b2061 bp 0x10c0000c7160 sp 0x10c0000c7148 T0)
+SCARINESS: 10 (signal)
+    #0 0x5b2061 in runtime.raise.abi0 runtime/sys_linux_amd64.s:165
+AddressSanitizer can not provide additional info.
+SUMMARY: AddressSanitizer: ABRT (/mnt/scratch0/clusterfuzz/bot/builds/clusterfuzz-builds_gonids_4fd1d07459dc0e09cc34419f8d397495d6d91ed0/revisions/fuzz_parserule+0x5b2061)
+==16820==ABORTING
diff --git a/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_data/sanitizer_oom.txt b/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_data/sanitizer_oom.txt
new file mode 100644
--- /dev/null
+++ b/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_data/sanitizer_oom.txt
@@ -0,0 +1,25 @@
+=================================================================
+==2314613==ERROR: AddressSanitizer: out of memory: allocator is trying to allocate 0x40000004 bytes
+==2314613==WARNING: invalid path to external symbolizer!
+==2314613==WARNING: Failed to use and restart external symbolizer!
+    #0 0x567b659f in operator new[](unsigned int) third_party/llvm/compiler-rt/lib/asan/asan_new_delete.cpp:98:3
+    #1 0xf56bd13b in NewForOverwrite v8/src/base/vector.h:257:48
+    #2 0xf56bd13b in v8::internal::wasm::AsyncStreamingDecoder::SectionBuffer::SectionBuffer(unsigned int, unsigned char, unsigned int, v8::base::Vector<unsigned char const>) v8/src/wasm/streaming-decoder.cc:58:18
+    #3 0xf56b3600 in __shared_ptr_emplace<unsigned int &, unsigned char &, unsigned int &, v8::base::Vector<const unsigned char> &> buildtools/third_party/libc++/trunk/include/__memory/shared_ptr.h:295:37
+    #4 0xf56b3600 in allocate_shared<v8::internal::wasm::AsyncStreamingDecoder::SectionBuffer, std::Cr::allocator<v8::internal::wasm::AsyncStreamingDecoder::SectionBuffer>, unsigned int &, unsigned char &, unsigned int &, v8::base::Vector<const unsigned char> &, void> buildtools/third_party/libc++/trunk/include/__memory/shared_ptr.h:954:55
+    #5 0xf56b3600 in make_shared<v8::internal::wasm::AsyncStreamingDecoder::SectionBuffer, unsigned int &, unsigned char &, unsigned int &, v8::base::Vector<const unsigned char> &, void> buildtools/third_party/libc++/trunk/include/__memory/shared_ptr.h:963:12
+    #6 0xf56b3600 in v8::internal::wasm::AsyncStreamingDecoder::CreateNewBuffer(unsigned int, unsigned char, unsigned int, v8::base::Vector<unsigned char const>) v8/src/wasm/streaming-decoder.cc:727:33
+    #7 0xf56b2858 in v8::internal::wasm::AsyncStreamingDecoder::DecodeSectionLength::NextWithValue(v8::internal::wasm::AsyncStreamingDecoder*) v8/src/wasm/streaming-decoder.cc:606:18
+    #8 0xf56b0dc9 in v8::internal::wasm::AsyncStreamingDecoder::DecodeVarInt32::Next(v8::internal::wasm::AsyncStreamingDecoder*) v8/src/wasm/streaming-decoder.cc:571:10
+    #9 0xf56abc18 in v8::internal::wasm::AsyncStreamingDecoder::OnBytesReceived(v8::base::Vector<unsigned char const>) v8/src/wasm/streaming-decoder.cc:240:24
+    #10 0x567b928d in v8::internal::wasm::CompileStreaming(v8_fuzzer::FuzzerSupport*, v8::internal::wasm::WasmFeatures, v8::base::Vector<unsigned char const>, unsigned char) v8/test/fuzzer/wasm-streaming.cc:100:15
+    #11 0x567bbc5b in LLVMFuzzerTestOneInput v8/test/fuzzer/wasm-streaming.cc:168:7
+    #12 0x5686eea0 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned int) third_party/libFuzzer/src/FuzzerLoop.cpp:556:15
+    #13 0x56811d77 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned int) third_party/libFuzzer/src/FuzzerDriver.cpp:292:6
+    #14 0x5681a559 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned int)) third_party/libFuzzer/src/FuzzerDriver.cpp:774:9
+    #15 0x568eca25 in main third_party/libFuzzer/src/FuzzerMain.cpp:19:10
+    #16 0xed7b2ed4 in __libc_start_main
+==2314613==HINT: if you don't care about these errors you may set allocator_may_return_null=1
+SUMMARY: AddressSanitizer: out-of-memory (/mnt/scratch0/clusterfuzz/bot/builds/chromium-browser-libfuzzer_linux32-debug-asan-arm-sim_8549b81cb96e1c3ffd1f9971ac37f1951947d713/revisions/libfuzzer-v8-arm-linux32-debug-1021657/v8_wasm_streaming_fuzzer+0x1d959f) (BuildId: 8173722a4fa988d8)
+==2314613==ABORTING
+
diff --git a/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_test.py b/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_test.py
--- a/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_test.py
+++ b/src/clusterfuzz/_internal/tests/core/crash_analysis/stack_parsing/stack_analyzer_test.py
@@ -3268,3 +3268,37 @@ def test_capture_command_injection(self):
     self._validate_get_crash_data(data, expected_type, expected_address,
                                   expected_state, expected_stacktrace,
                                   expected_security_flag)
+
+  def test_sanitizer_out_of_memory(self):
+    """Test sanitizer out of memory."""
+    os.environ['REPORT_OOMS_AND_HANGS'] = 'True'
+    data = self._read_test_data('sanitizer_oom.txt')
+    expected_type = 'Out-of-memory'
+    expected_address = ''
+    expected_state = (
+        'v8::internal::wasm::AsyncStreamingDecoder::SectionBuffer::'
+        'SectionBuffer\n'
+        'v8::internal::wasm::AsyncStreamingDecoder::CreateNewBuffer\n'
+        'v8::internal::wasm::AsyncStreamingDecoder::DecodeSectionLength::'
+        'NextWithValue\n')
+
+    expected_stacktrace = data
+    expected_security_flag = False
+    self._validate_get_crash_data(data, expected_type, expected_address,
+                                  expected_state, expected_stacktrace,
+                                  expected_security_flag)
+
+  def test_go_braces(self):
+    """Test Go stacktrace parsing (with braces in the frame string)."""
+    data = self._read_test_data('go_braces.txt')
+    expected_type = 'Slice bounds out of range'
+    expected_address = ''
+    expected_state = ('regexp.(*Regexp).Split\n'
+                      'gonids.(*Rule).option\n'
+                      'gonids.parseRuleAux\n')
+
+    expected_stacktrace = data
+    expected_security_flag = False
+    self._validate_get_crash_data(data, expected_type, expected_address,
+                                  expected_state, expected_stacktrace,
+                                  expected_security_flag)