vitess.io/vitess@v0.16.2/go/vt/vtgate/engine/fuzz.go (about)

     1  //go:build gofuzz
     2  // +build gofuzz
     3  
     4  /*
     5  Copyright 2021 The Vitess Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  /*
    21  	DEPENDENCIES:
    22  	This fuzzer relies heavily on
    23  	$VTROOT/go/vt/vtgate/engine/fake_vcursor_test.go,
    24  	and in order to run it, it is required to rename:
    25  	$VTROOT/go/vt/vtgate/engine/fake_vcursor_test.go
    26  	to
    27  	$VTROOT/go/vt/vtgate/engine/fake_vcursor.go
    28  
    29  	This is handled by the OSS-fuzz build script and
    30  	is only important to make note of if the fuzzer
    31  	is run locally.
    32  
    33  	STATUS:
    34  	The fuzzer does not currently implement executions
    35  	for all possible API's in the engine package, and
    36  	it can be considered experimental, as I (@AdamKorcz)
    37  	am interested in its performance when being run
    38  	continuously by OSS-fuzz. Needless to say, more
    39  	APIs can be added with ease.
    40  */
    41  
    42  package engine
    43  
    44  import (
    45  	fuzz "github.com/AdaLogics/go-fuzz-headers"
    46  
    47  	querypb "vitess.io/vitess/go/vt/proto/query"
    48  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    49  )
    50  
    51  // FuzzEngine implements the fuzzer
    52  func FuzzEngine(data []byte) int {
    53  	c := fuzz.NewConsumer(data)
    54  
    55  	index, err := c.GetInt()
    56  	if err != nil {
    57  		return 0
    58  	}
    59  	switch i := index % 3; i {
    60  	case 0:
    61  		execUpdate(c)
    62  	case 1:
    63  		execInsert(c)
    64  	case 2:
    65  		execRoute(c)
    66  	default:
    67  		return 0
    68  	}
    69  	return 1
    70  }
    71  
    72  // execUpdate implements a wrapper to fuzz Update.Tryexecute()
    73  func execUpdate(f *fuzz.ConsumeFuzzer) {
    74  	upd := &Update{}
    75  	err := f.GenerateStruct(upd)
    76  	if err != nil {
    77  		return
    78  	}
    79  	vc := &loggingVCursor{}
    80  	_, _ = upd.TryExecute(ctx, vc, map[string]*querypb.BindVariable{}, false)
    81  }
    82  
    83  // execUpdate implements a wrapper to fuzz Insert.Tryexecute()
    84  func execInsert(f *fuzz.ConsumeFuzzer) {
    85  	ins := &Insert{}
    86  	err := f.GenerateStruct(ins)
    87  	if err != nil {
    88  		return
    89  	}
    90  	vc := &loggingVCursor{}
    91  	_, _ = ins.TryExecute(ctx, vc, map[string]*querypb.BindVariable{}, false)
    92  }
    93  
    94  // execUpdate implements a wrapper to fuzz Route.Tryexecute()
    95  func execRoute(f *fuzz.ConsumeFuzzer) {
    96  	sel := &Route{}
    97  	err := f.GenerateStruct(sel)
    98  	if err != nil {
    99  		return
   100  	}
   101  	vc := newFuzzDMLTestVCursor("0")
   102  	_, _ = sel.TryExecute(ctx, vc, map[string]*querypb.BindVariable{}, false)
   103  }
   104  
   105  func newFuzzDMLTestVCursor(shards ...string) *loggingVCursor {
   106  	return &loggingVCursor{shards: shards, resolvedTargetTabletType: topodatapb.TabletType_PRIMARY}
   107  }