github.com/lzhfromustc/gofuzz@v0.0.0-20211116160056-151b3108bbd1/runtime/myselect.go (about) 1 package runtime 2 3 import "sync/atomic" 4 5 var MapSelectInfo map[string]SelectInfo // useful only when RecordSelectChoice is true 6 //var MapInput map[string]SelectInfo // useful only when RecordSelectChoice is false 7 var RecordSelectChoice bool = false 8 var MuFirstInput mutex 9 var Uint32SelectCount uint32 10 var BoolSelectCount bool 11 12 13 14 type SelectInfo struct { 15 StrFileName string 16 StrLineNum string 17 IntNumCase int 18 IntPrioCase int 19 } 20 21 func StoreSelectInput(intNumCase, intChosenCase int) { 22 newSelectInput := NewSelectInputFromRuntime(intNumCase, intChosenCase, 3) 23 if newSelectInput.IntNumCase != 0 { // IntNumCase would be 0 if this select is not instrumented (e.g., in SDK) and we can't mutate it 24 lock(&MuFirstInput) 25 MapSelectInfo[newSelectInput.StrFileName + ":" + newSelectInput.StrLineNum] = newSelectInput 26 unlock(&MuFirstInput) 27 } 28 } 29 30 func NewSelectInputFromRuntime(intNumCase, intPrioCase int, intLayerCallee int) SelectInfo { 31 // if A contains select, select calls StoreSelectInput, StoreSelectInput calls this function, then intLayerCallee is 3 32 const size = 64 << 10 33 buf := make([]byte, size) 34 buf = buf[:Stack(buf, false)] 35 strStack := string(buf) 36 stackSingleGo := ParseStackStr(strStack) 37 if len(stackSingleGo.VecFuncLine) < intLayerCallee { 38 return SelectInfo{} 39 } 40 selectInput := SelectInfo{ 41 StrFileName: stackSingleGo.VecFuncFile[intLayerCallee - 1], // where is the select 42 StrLineNum: LastMySwitchLineNum(), 43 IntNumCase: LastMySwitchOriSelectNumCase(), 44 IntPrioCase: -1, 45 } 46 47 if LastMySwitchChoice() == -1 { 48 // Executing the original select 49 selectInput.IntPrioCase = intPrioCase 50 } else { 51 // Executing our select, so the chosen case is same to switch's choice 52 selectInput.IntPrioCase = LastMySwitchChoice() 53 } 54 55 return selectInput 56 } 57 58 func LastMySwitchLineNum() string { 59 if getg().lastMySwitchLineNum != "" { 60 return getg().lastMySwitchLineNum 61 } else { 62 return "0" 63 } 64 } 65 66 func LastMySwitchOriSelectNumCase() int { 67 return getg().lastMySwitchOriSelectNumCase 68 } 69 70 func LastMySwitchChoice() int { 71 return getg().lastMySwitchChoice 72 } 73 74 func StoreLastMySwitchSelectNumCase(numCase int) { 75 getg().lastMySwitchOriSelectNumCase = numCase 76 } 77 78 func StoreLastMySwitchChoice(choice int) { 79 getg().lastMySwitchChoice = choice 80 } 81 82 func StoreLastMySwitchLineNum(strLine string) { 83 getg().lastMySwitchLineNum = strLine // no need for synchronization. 84 } 85 86 func SelectCount() { 87 atomic.AddUint32(&Uint32SelectCount, 1) 88 } 89 90 func ReadSelectCount() uint32 { 91 return atomic.LoadUint32(&Uint32SelectCount) 92 }