github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/prog/parse.go (about) 1 // Copyright 2015 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package prog 5 6 import ( 7 "bytes" 8 "strconv" 9 ) 10 11 // LogEntry describes one program in execution log. 12 type LogEntry struct { 13 P *Prog 14 Proc int // index of parallel proc 15 Start int // start offset in log 16 End int // end offset in log 17 } 18 19 func (target *Target) ParseLog(data []byte) []*LogEntry { 20 var entries []*LogEntry 21 ent := &LogEntry{} 22 var cur []byte 23 faultCall, faultNth := -1, -1 24 for pos := 0; pos < len(data); { 25 nl := bytes.IndexByte(data[pos:], '\n') 26 if nl == -1 { 27 nl = len(data) - 1 28 } else { 29 nl += pos 30 } 31 line := data[pos : nl+1] 32 pos0 := pos 33 pos = nl + 1 34 35 if proc, ok := extractInt(line, "executing program "); ok { 36 if ent.P != nil && len(ent.P.Calls) != 0 { 37 ent.End = pos0 38 entries = append(entries, ent) 39 faultCall, faultNth = -1, -1 40 } 41 ent = &LogEntry{ 42 Proc: proc, 43 Start: pos0, 44 } 45 // We no longer print it this way, but we still parse such fragments to preserve 46 // the backward compatibility. 47 if parsedFaultCall, ok := extractInt(line, "fault-call:"); ok { 48 faultCall = parsedFaultCall 49 faultNth, _ = extractInt(line, "fault-nth:") 50 } 51 cur = nil 52 continue 53 } 54 55 tmp := append(cur, line...) 56 57 p, err := target.Deserialize(tmp, NonStrict) 58 if err != nil { 59 continue 60 } 61 62 if faultCall >= 0 && faultCall < len(p.Calls) { 63 // We add 1 because now the property is 1-based. 64 p.Calls[faultCall].Props.FailNth = faultNth + 1 65 } 66 67 cur = tmp 68 ent.P = p 69 } 70 if ent.P != nil && len(ent.P.Calls) != 0 { 71 ent.End = len(data) 72 entries = append(entries, ent) 73 } 74 return entries 75 } 76 77 func extractInt(line []byte, prefix string) (int, bool) { 78 pos := bytes.Index(line, []byte(prefix)) 79 if pos == -1 { 80 return 0, false 81 } 82 pos += len(prefix) 83 end := pos 84 for end != len(line) && line[end] >= '0' && line[end] <= '9' { 85 end++ 86 } 87 v, _ := strconv.Atoi(string(line[pos:end])) 88 return v, true 89 }