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  }