github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/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 ID int // ID of the executed program (-1 if not present) 16 Start int // start offset in log 17 End int // end offset in log 18 } 19 20 func (target *Target) ParseLog(data []byte, mode DeserializeMode) []*LogEntry { 21 var entries []*LogEntry 22 ent := &LogEntry{ 23 ID: -1, 24 } 25 var cur []byte 26 faultCall, faultNth := -1, -1 27 for pos := 0; pos < len(data); { 28 nl := bytes.IndexByte(data[pos:], '\n') 29 if nl == -1 { 30 nl = len(data) - 1 31 } else { 32 nl += pos 33 } 34 line := data[pos : nl+1] 35 pos0 := pos 36 pos = nl + 1 37 38 if proc, ok := extractInt(line, "executing program "); ok { 39 if ent.P != nil && len(ent.P.Calls) != 0 { 40 ent.End = pos0 41 entries = append(entries, ent) 42 faultCall, faultNth = -1, -1 43 } 44 ent = &LogEntry{ 45 Proc: proc, 46 Start: pos0, 47 ID: -1, 48 } 49 if id, ok := extractInt(line, "id="); ok { 50 ent.ID = id 51 } 52 // We no longer print it this way, but we still parse such fragments to preserve 53 // the backward compatibility. 54 if parsedFaultCall, ok := extractInt(line, "fault-call:"); ok { 55 faultCall = parsedFaultCall 56 faultNth, _ = extractInt(line, "fault-nth:") 57 } 58 cur = nil 59 continue 60 } 61 62 tmp := append(cur, line...) 63 64 p, err := target.Deserialize(tmp, mode) 65 if err != nil { 66 continue 67 } 68 69 if faultCall >= 0 && faultCall < len(p.Calls) { 70 // We add 1 because now the property is 1-based. 71 p.Calls[faultCall].Props.FailNth = faultNth + 1 72 } 73 74 cur = tmp 75 ent.P = p 76 } 77 if ent.P != nil && len(ent.P.Calls) != 0 { 78 ent.End = len(data) 79 entries = append(entries, ent) 80 } 81 return entries 82 } 83 84 func extractInt(line []byte, prefix string) (int, bool) { 85 pos := bytes.Index(line, []byte(prefix)) 86 if pos == -1 { 87 return 0, false 88 } 89 pos += len(prefix) 90 end := pos 91 for end != len(line) && line[end] >= '0' && line[end] <= '9' { 92 end++ 93 } 94 v, _ := strconv.Atoi(string(line[pos:end])) 95 return v, true 96 }