func parseExploitable(raw []byte, ci *crash.Info, die func()) { scanner := bufio.NewScanner(bytes.NewReader(raw)) // Faulting frame: # 4 None at 0x7ffff6fad93b in /usr/lib/x86_64-linux-gnu/libcairo.so.2.11301.0 // Faulting frame: # 6 operator new(unsigned long) at 0x7ffff6d87698 in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.20 // [ <---ignore---> ] [ symbol text until "at" ] [address] [ <-- module from here--> ] mustAdvanceTo("Faulting frame:", scanner, die) ff := strings.Fields(scanner.Text()) if len(ff) < 9 { die() } atIdx := 0 for i := 0; i < len(ff); i++ { if ff[i] == "at" { atIdx = i break } } if atIdx == 0 { die() } ci.FaultingFrame = crash.StackEntry{ Symbol: strings.Join(ff[4:atIdx], " "), Address: mustParseHex(ff[atIdx+1], die), // don't know if modules can ever contain spaces? Module: strings.Join(ff[atIdx+3:], " "), } // Description: Abort signal mustAddExtra("Description:", scanner, ci, die) // Short description: AbortSignal (20/22) mustAddExtra("Short description:", scanner, ci, die) // Hash: 71c14ffe39944b60af6fd47d1e505f97.0822ff5e99ce7ad4a1e6e98b273082a7 mustAdvanceTo("Hash:", scanner, die) ci.Hash = strings.Fields(scanner.Text())[1] // Exploitability Classification: UNKNOWN mustAdvanceTo("Exploitability", scanner, die) ci.Classification = strings.Fields(scanner.Text())[2] // Explanation: The target is stopped on a SIGABRT. [...] mustAddExtra("Explanation:", scanner, ci, die) return }
func parseStack(raw []byte, ci *crash.Info, die func()) { // Stack trace: // * thread #1: tid = 0x9f2fa1f, 0x00007fff97580282 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT // * frame #0: 0x00007fff97580282 libsystem_kernel.dylib`__pthread_kill + 10 // frame #1: 0x00007fff8e3d54c3 libsystem_pthread.dylib`pthread_kill + 90 // frame #2: 0x00007fff97a4cb73 libsystem_c.dylib`abort + 129 // frame #3: 0x00000001000b4dc4 pdftoppm`Catalog::getNumPages() [inlined] Object::dictIs(this=0x0000000000000007, dictType=<unavailable>) - 18446744069413843515 // frame #4: 0x00000001000029c0 pdftoppm`main(argc=2, argv=<unavailable>) - 18446744069414573631 // frame #5: 0x00007fff9a2f35c9 libdyld.dylib`start + 1 // frame #6: 0x00007fff9a2f35c9 libdyld.dylib`start + 1 scanner := bufio.NewScanner(bytes.NewReader(raw)) mustAdvanceTo("Stack trace:", scanner, die) scanner.Scan() ff := strings.Fields(scanner.Text()) if len(ff) < 8 || ff[1] != "thread" { die() } for scanner.Scan() { // scan until we run out of frames ff := strings.Fields(scanner.Text()) if len(ff) == 0 { break } // A leading asterisk adjusts all our offsets by 1 adjust := 0 if ff[0] == "*" { adjust++ } if ff[0+adjust] != "frame" { break } if len(ff) < 3 { die() } var address uint64 var found bool for _, s := range ff { if strings.HasPrefix(s, "0x") { address = mustParseHex(s, die) found = true } } if !found { die() } splits := []string{"???", "???"} if len(ff) > 3+adjust { // split on backtick (`) // libsystem_pthread.dylib`pthread_kill + 90 rest := strings.Join(ff[3+adjust:], " ") splits = strings.SplitN(rest, "`", 2) if len(splits) < 2 { die() } } entry := crash.StackEntry{ Address: address, Module: splits[0], Symbol: splits[1], } ci.Stack = append(ci.Stack, entry) } // Set the fault to the first frame that's not blacklisted walk: for _, frame := range ci.Stack { for _, r := range blacklist { if r.MatchString(frame.Module) { continue walk } } ci.FaultingFrame = frame break } // don't be too fussy about not finding a stack, here, some crashes set // those registers to values that are unreadable as addresses. return }