// Copyright (c) 2016 Marty Schoch// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the// License. You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0// Unless required by applicable law or agreed to in writing,// software distributed under the License is distributed on an "AS// IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either// express or implied. See the License for the specific language// governing permissions and limitations under the License.package smatimport ()// Logger is a configurable logger used by this package// by default output is discardedvarLogger = log.New(ioutil.Discard, "smat ", log.LstdFlags)// Context is a container for any user statetypeContextinterface{}// State is a function which describes which action to perform in the event// that a particular byte is seentypeStatefunc(next byte) ActionID// PercentAction describes the frequency with which an action should occur// for example: Action{Percent:10, Action:DonateMoney} means that 10% of// the time you should donate money.typePercentActionstruct { Percent int Action ActionID}// Action is any function which returns the next state to transition to// it can optionally mutate the provided context object// if any error occurs, it may return an error which will abort executiontypeActionfunc(Context) (State, error)// ActionID is a unique identifier for an actiontypeActionIDint// NopAction does nothing and simply continues to the next inputvarNopActionActionID = -1// ActionMap is a mapping form ActionID to ActiontypeActionMapmap[ActionID]Actionfunc ( ActionMap) (, ActionID) (Action, Action, error) { , := []if ! {returnnil, nil, ErrSetupMissing } , := []if ! {returnnil, nil, ErrTeardownMissing }return , , nil}// Fuzz runs the fuzzing state machine with the provided context// first, the setup action is executed unconditionally// the start state is determined by this action// actionMap is a lookup table for all actions// the data byte slice determines all future state transitions// finally, the teardown action is executed unconditionally for cleanupfunc ( Context, , ActionID, ActionMap, []byte) int { := bytes.NewReader() := runReader(, , , , , nil)if != nil {panic() }return1}// Longevity runs the state machine with the provided context// first, the setup action is executed unconditionally// the start state is determined by this action// actionMap is a lookup table for all actions// random bytes are generated to determine all future state transitions// finally, the teardown action is executed unconditionally for cleanupfunc ( Context, , ActionID, ActionMap, int64, chanstruct{}) error { := rand.NewSource()returnrunReader(, , , , rand.New(), )}var (// ErrSetupMissing is returned when the setup action cannot be foundErrSetupMissing = fmt.Errorf("setup action missing")// ErrTeardownMissing is returned when the teardown action cannot be foundErrTeardownMissing = fmt.Errorf("teardown action missing")// ErrClosed is returned when the closeChan was closed to cancel the opErrClosed = fmt.Errorf("closed")// ErrActionNotPossible is returned when an action is encountered in a // FuzzCase that is not possible in the current stateErrActionNotPossible = fmt.Errorf("action not possible in state"))func runReader( Context, , ActionID, ActionMap, io.Reader, chanstruct{}) error { , , := .findSetupTeardown(, )if != nil {return }Logger.Printf("invoking setup action") , := ()if != nil {return }deferfunc() {Logger.Printf("invoking teardown action") _, _ = () }() := bufio.NewReader()for , := .ReadByte(); == nil; , = .ReadByte() {select {case<-:returnErrCloseddefault: := () , := []if ! {Logger.Printf("no such action defined, continuing")continue }Logger.Printf("invoking action - %d", ) , = ()if != nil {Logger.Printf("it was action %d that returned err %v", , )return } } }return}// PercentExecute interprets the next byte as a random value and normalizes it// to values 0-99, it then looks to see which action should be execued based// on the action distributionsfunc ( byte, ...PercentAction) ActionID { := int(99 * int() / 255) := 0for , := range { = + .Percentif < {return .Action } }returnNopAction}
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.