Upgrade github.com/AdaLogics/go-fuzz-headers
Signed-off-by: Kazuyoshi Kato <katokazu@amazon.com>
This commit is contained in:
		
							
								
								
									
										3
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							| @@ -3,7 +3,7 @@ module github.com/containerd/containerd | ||||
| go 1.18 | ||||
|  | ||||
| require ( | ||||
| 	github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8 | ||||
| 	github.com/AdaLogics/go-fuzz-headers v0.0.0-20220706123152-fef3fe1bab07 | ||||
| 	github.com/Microsoft/go-winio v0.5.2 | ||||
| 	github.com/Microsoft/hcsshim v0.9.2 | ||||
| 	github.com/container-orchestrated-devices/container-device-interface v0.3.1 | ||||
| @@ -85,6 +85,7 @@ require ( | ||||
| 	github.com/containernetworking/cni v1.1.1 // indirect | ||||
| 	github.com/containers/ocicrypt v1.1.3 // indirect | ||||
| 	github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect | ||||
| 	github.com/cyphar/filepath-securejoin v0.2.3 // indirect | ||||
| 	github.com/emicklei/go-restful v2.9.5+incompatible // indirect | ||||
| 	github.com/go-logr/logr v1.2.3 // indirect | ||||
| 	github.com/go-logr/stdr v1.2.2 // indirect | ||||
|   | ||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @@ -40,8 +40,9 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl | ||||
| cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= | ||||
| cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= | ||||
| dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8 h1:V8krnnfGj4pV65YLUm3C0/8bl7V5Nry2Pwvy3ru/wLc= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20220706123152-fef3fe1bab07 h1:7dZd6IhJApT69RGnt+YHRRVHXkO9fA6tAdl5E7iG9EU= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20220706123152-fef3fe1bab07/go.mod h1:i9fr2JpcEcY/IHEvzCM3qXUZYOQHgR89dt4es1CgMhc= | ||||
| github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= | ||||
| github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= | ||||
| github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= | ||||
| @@ -322,6 +323,7 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do | ||||
| github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | ||||
| github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | ||||
| github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= | ||||
| github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= | ||||
| github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= | ||||
| github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= | ||||
| github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= | ||||
|   | ||||
| @@ -19,7 +19,7 @@ require ( | ||||
| 	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a | ||||
| ) | ||||
|  | ||||
| require github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8 | ||||
| require github.com/AdaLogics/go-fuzz-headers v0.0.0-20220706123152-fef3fe1bab07 | ||||
|  | ||||
| require ( | ||||
| 	github.com/Microsoft/go-winio v0.5.2 // indirect | ||||
| @@ -30,6 +30,7 @@ require ( | ||||
| 	github.com/containerd/continuity v0.3.0 // indirect | ||||
| 	github.com/containerd/fifo v1.0.0 // indirect | ||||
| 	github.com/coreos/go-systemd/v22 v22.3.2 // indirect | ||||
| 	github.com/cyphar/filepath-securejoin v0.2.3 // indirect | ||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||
| 	github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect | ||||
| 	github.com/docker/go-units v0.4.0 // indirect | ||||
|   | ||||
| @@ -38,8 +38,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl | ||||
| cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= | ||||
| cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= | ||||
| dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8 h1:V8krnnfGj4pV65YLUm3C0/8bl7V5Nry2Pwvy3ru/wLc= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20220706123152-fef3fe1bab07 h1:7dZd6IhJApT69RGnt+YHRRVHXkO9fA6tAdl5E7iG9EU= | ||||
| github.com/AdaLogics/go-fuzz-headers v0.0.0-20220706123152-fef3fe1bab07/go.mod h1:i9fr2JpcEcY/IHEvzCM3qXUZYOQHgR89dt4es1CgMhc= | ||||
| github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= | ||||
| github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= | ||||
| github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= | ||||
| @@ -186,6 +186,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t | ||||
| github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | ||||
| github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= | ||||
| github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= | ||||
| github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= | ||||
| github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= | ||||
| github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= | ||||
| github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= | ||||
|   | ||||
							
								
								
									
										114
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										114
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,49 +1,93 @@ | ||||
| # go-fuzz-headers | ||||
| This repository contains various helper functions to be used with [go-fuzz](https://github.com/dvyukov/go-fuzz). | ||||
| This repository contains various helper functions for go fuzzing. It is mostly used in combination with [go-fuzz](https://github.com/dvyukov/go-fuzz), but compatibility with fuzzing in the standard library will also be supported. Any coverage guided fuzzing engine that provides an array or slice of bytes can be used with go-fuzz-headers. | ||||
|  | ||||
| ## Goal | ||||
|  | ||||
| The current goal of go-fuzz-headers is: | ||||
| To maintain a series of helper utilities that can be used for golang projects that are integrated into OSS-fuzz and use the go-fuzz engine to fuzz more complicated types than merely strings and data arrays.  | ||||
| While go-fuzz-headers can be used when using go-fuzz outside of OSS-fuzz, we do not test such usage and cannot confirm that it is supported. | ||||
|  | ||||
| ## Status | ||||
|  | ||||
| The project is under development and will be updated regularly. | ||||
|  | ||||
| Fuzzers that use `GenerateStruct` will not require modifications as more types get supported. | ||||
|  | ||||
| ## Usage | ||||
| To make use of the helper functions, a ConsumeFuzzer has to be instantiated: | ||||
| Using go-fuzz-headers is easy. First create a new consumer with the bytes provided by the fuzzing engine: | ||||
|  | ||||
| ```go | ||||
| f := NewConsumer(data) | ||||
| import ( | ||||
| 	fuzz "github.com/AdaLogics/go-fuzz-headers" | ||||
| ) | ||||
| data := []byte{'R', 'a', 'n', 'd', 'o', 'm'} | ||||
| f := fuzz.NewConsumer(data) | ||||
|  | ||||
| ``` | ||||
| To split the input data from the fuzzer into a random set of equally large chunks: | ||||
|  | ||||
| This creates a `Consumer` that consumes the bytes of the input as it uses them to fuzz different types. | ||||
|  | ||||
| After that, `f` can be used to easily create fuzzed instances of different types. Below are some examples: | ||||
|  | ||||
| ### Structs | ||||
| One of the most useful features of go-fuzz-headers is its ability to fill structs with the data provided by the fuzzing engine. This is done with a single line: | ||||
| ```go | ||||
| err := f.Split(3, 6) | ||||
| type Person struct { | ||||
|     Name string | ||||
|     Age  int | ||||
| } | ||||
| p := Person{} | ||||
| // Fill p with values based on the data provided by the fuzzing engine: | ||||
| err := f.GenerateStruct(&p) | ||||
| ``` | ||||
| ...after which the consumer has the following available attributes: | ||||
|  | ||||
| This includes nested structs too. In this example, the fuzz Consumer will also insert values in `p.BestFriend`: | ||||
| ```go | ||||
| f.CommandPart = commandPart | ||||
| f.RestOfArray = restOfArray | ||||
| f.NumberOfCalls = numberOfCalls | ||||
| type PersonI struct { | ||||
|     Name       string | ||||
|     Age        int | ||||
|     BestFriend PersonII | ||||
| } | ||||
| type PersonII struct { | ||||
|     Name string | ||||
|     Age  int | ||||
| } | ||||
| p := PersonI{} | ||||
| err := f.GenerateStruct(&p) | ||||
| ``` | ||||
| To pass the input data from the fuzzer into a struct: | ||||
|  | ||||
| If the consumer should insert values for unexported fields as well as exported, this can be enabled with: | ||||
|  | ||||
| ```go | ||||
| ts := new(target_struct) | ||||
| err :=f.GenerateStruct(ts) | ||||
| f.AllowUnexportedFields() | ||||
| ``` | ||||
| or: | ||||
|  | ||||
| ...and disabled with: | ||||
|  | ||||
| ```go | ||||
| ts := target_struct{} | ||||
| err = f.GenerateStruct(&ts) | ||||
| f.DisallowUnexportedFields() | ||||
| ``` | ||||
| `GenerateStruct` will pass data from the input data to the targeted struct. Currently the following field types are supported: | ||||
| 1. `string` | ||||
| 2. `bool` | ||||
| 3. `int` | ||||
| 4. `[]string` | ||||
| 5. `byte` | ||||
| 5. `[]byte` | ||||
| 6. custom structures | ||||
| 7. `map` | ||||
|  | ||||
| ### Other types: | ||||
|  | ||||
| Other useful APIs: | ||||
|  | ||||
| ```go | ||||
| createdString, err := f.GetString() // Gets a string | ||||
| createdInt, err := f.GetInt() // Gets an integer | ||||
| createdByte, err := f.GetByte() // Gets a byte | ||||
| createdBytes, err := f.GetBytes() // Gets a byte slice | ||||
| createdBool, err := f.GetBool() // Gets a boolean | ||||
| err := f.FuzzMap(target_map) // Fills a map | ||||
| createdTarBytes, err := f.TarBytes() // Gets bytes of a valid tar archive | ||||
| err := f.CreateFiles(inThisDir) // Fills inThisDir with files | ||||
| createdString, err := f.GetStringFrom("anyCharInThisString", ofThisLength) // Gets a string that consists of chars from "anyCharInThisString" and has the exact length "ofThisLength" | ||||
| ``` | ||||
|  | ||||
| Most APIs are added as they are needed. | ||||
|  | ||||
| ## Projects that use go-fuzz-headers | ||||
| - [runC](https://github.com/opencontainers/runc) | ||||
| - [Istio](https://github.com/istio/istio) | ||||
| - [Vitess](https://github.com/vitessio/vitess) | ||||
| - [Containerd](https://github.com/containerd/containerd) | ||||
|  | ||||
| Feel free to add your own project to the list, if you use go-fuzz-headers to fuzz it. | ||||
|  | ||||
|  | ||||
|   | ||||
|  | ||||
| ## Status | ||||
| The project is under development and will be updated regularly. | ||||
|  | ||||
| ## References | ||||
| go-fuzz-headers' approach to fuzzing structs is strongly inspired by [gofuzz](https://github.com/google/gofuzz). | ||||
							
								
								
									
										390
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/consumer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										390
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/consumer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,10 +3,17 @@ package gofuzzheaders | ||||
| import ( | ||||
| 	"archive/tar" | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	//"fmt" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"unsafe" | ||||
|  | ||||
| 	securejoin "github.com/cyphar/filepath-securejoin" | ||||
| ) | ||||
|  | ||||
| type ConsumeFuzzer struct { | ||||
| @@ -16,14 +23,20 @@ type ConsumeFuzzer struct { | ||||
| 	NumberOfCalls        int | ||||
| 	position             int | ||||
| 	fuzzUnexportedFields bool | ||||
| 	Funcs                map[reflect.Type]reflect.Value | ||||
| } | ||||
|  | ||||
| func IsDivisibleBy(n int, divisibleby int) bool { | ||||
| 	return (n % divisibleby) == 0 | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) BytesLeft() int { | ||||
| 	return len(f.data) - f.position | ||||
| } | ||||
|  | ||||
| func NewConsumer(fuzzData []byte) *ConsumeFuzzer { | ||||
| 	f := &ConsumeFuzzer{data: fuzzData, position: 0} | ||||
| 	fuzzMap := make(map[reflect.Type]reflect.Value) | ||||
| 	f := &ConsumeFuzzer{data: fuzzData, position: 0, Funcs: fuzzMap} | ||||
| 	return f | ||||
| } | ||||
|  | ||||
| @@ -73,32 +86,100 @@ func (f *ConsumeFuzzer) GenerateStruct(targetStruct interface{}) error { | ||||
| 		return errors.New("This interface cannot be set") | ||||
| 	}*/ | ||||
| 	e := v.Elem() | ||||
| 	err := f.fuzzStruct(e) | ||||
| 	err := f.fuzzStruct(e, false) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value) error { | ||||
| func (f *ConsumeFuzzer) setCustom(v reflect.Value) error { | ||||
| 	// First: see if we have a fuzz function for it. | ||||
| 	doCustom, ok := f.Funcs[v.Type()] | ||||
| 	if !ok { | ||||
| 		return fmt.Errorf("Could not find a custom function") | ||||
| 	} | ||||
|  | ||||
| 	switch v.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		if v.IsNil() { | ||||
| 			if !v.CanSet() { | ||||
| 				return fmt.Errorf("Could not use a custom function") | ||||
| 			} | ||||
| 			v.Set(reflect.New(v.Type().Elem())) | ||||
| 		} | ||||
| 	case reflect.Map: | ||||
| 		if v.IsNil() { | ||||
| 			if !v.CanSet() { | ||||
| 				return fmt.Errorf("Could not use a custom function") | ||||
| 			} | ||||
| 			v.Set(reflect.MakeMap(v.Type())) | ||||
| 		} | ||||
| 	default: | ||||
| 		return fmt.Errorf("Could not use a custom function") | ||||
| 	} | ||||
|  | ||||
| 	verr := doCustom.Call([]reflect.Value{v, reflect.ValueOf(Continue{ | ||||
| 		F: f, | ||||
| 	})}) | ||||
| 	// check if we return an error | ||||
| 	if verr[0].IsNil() { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return fmt.Errorf("Could not use a custom function") | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value, customFunctions bool) error { | ||||
|  | ||||
| 	// We check if we should check for custom functions | ||||
| 	if customFunctions { | ||||
| 		if e.IsValid() { | ||||
| 			if e.CanAddr() { | ||||
| 				err := f.setCustom(e.Addr()) | ||||
| 				if err == nil { | ||||
| 					return nil | ||||
| 				} | ||||
| 			} | ||||
| 			/*	return f.setCustom(e) | ||||
| 				_, ok := f.Funcs[e.Type()] | ||||
| 				if ok { | ||||
| 					if e.CanAddr() { | ||||
| 						err := f.setCustom(e.Addr()) | ||||
| 						if err == nil { | ||||
| 							return nil | ||||
| 						} | ||||
| 					}*/ | ||||
| 			//return f.setCustom(e) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	switch e.Kind() { | ||||
| 	case reflect.Struct: | ||||
| 		for i := 0; i < e.NumField(); i++ { | ||||
| 			// Useful for debugging, so we leave it for now: | ||||
| 			//vt := e.Type().Field(i).Name | ||||
| 			//fmt.Println("vt:::::::::::::::::::::: ", vt) | ||||
| 			var v reflect.Value | ||||
| 			if !e.Field(i).CanSet() { | ||||
| 				if f.fuzzUnexportedFields { | ||||
| 					v = reflect.NewAt(e.Field(i).Type(), unsafe.Pointer(e.Field(i).UnsafeAddr())).Elem() | ||||
| 				} | ||||
| 			} else { | ||||
| 				v = e.Field(i) | ||||
| 			} | ||||
| 			err := f.fuzzStruct(v) | ||||
| 				err := f.fuzzStruct(v, customFunctions) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} else { | ||||
| 				/*if e.Field(i).Kind() == reflect.Struct { | ||||
| 					//e = reflect.NewAt(e.Type(), unsafe.Pointer(e.UnsafeAddr())).Elem() | ||||
| 					//e.Field(i).Set(reflect.New(e.Field(i).Type())) | ||||
| 				}*/ | ||||
| 				v = e.Field(i) | ||||
| 				//v = reflect.New(e.Field(i).Type()) | ||||
| 				err := f.fuzzStruct(v, customFunctions) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				/*if e.Field(i).CanSet() { | ||||
| 					e.Field(i).Set(v.Elem()) | ||||
| 				}*/ | ||||
| 			} | ||||
| 		} | ||||
| 	case reflect.String: | ||||
| 		str, err := f.GetString() | ||||
| @@ -119,7 +200,7 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value) error { | ||||
| 		uu := reflect.MakeSlice(e.Type(), numOfElements, numOfElements) | ||||
|  | ||||
| 		for i := 0; i < numOfElements; i++ { | ||||
| 			err := f.fuzzStruct(uu.Index(i)) | ||||
| 			err := f.fuzzStruct(uu.Index(i), customFunctions) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| @@ -127,6 +208,22 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value) error { | ||||
| 		if e.CanSet() { | ||||
| 			e.Set(uu) | ||||
| 		} | ||||
| 	case reflect.Uint16: | ||||
| 		newInt, err := f.GetUint16() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if e.CanSet() { | ||||
| 			e.SetUint(uint64(newInt)) | ||||
| 		} | ||||
| 	case reflect.Uint32: | ||||
| 		newInt, err := f.GetUint32() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if e.CanSet() { | ||||
| 			e.SetUint(uint64(newInt)) | ||||
| 		} | ||||
| 	case reflect.Uint64: | ||||
| 		newInt, err := f.GetInt() | ||||
| 		if err != nil { | ||||
| @@ -135,7 +232,7 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value) error { | ||||
| 		if e.CanSet() { | ||||
| 			e.SetUint(uint64(newInt)) | ||||
| 		} | ||||
| 	case reflect.Int: | ||||
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 		newInt, err := f.GetInt() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| @@ -143,6 +240,22 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value) error { | ||||
| 		if e.CanSet() { | ||||
| 			e.SetInt(int64(newInt)) | ||||
| 		} | ||||
| 	case reflect.Float32: | ||||
| 		newFloat, err := f.GetFloat32() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if e.CanSet() { | ||||
| 			e.SetFloat(float64(newFloat)) | ||||
| 		} | ||||
| 	case reflect.Float64: | ||||
| 		newFloat, err := f.GetFloat64() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if e.CanSet() { | ||||
| 			e.SetFloat(float64(newFloat)) | ||||
| 		} | ||||
| 	case reflect.Map: | ||||
| 		if e.CanSet() { | ||||
| 			e.Set(reflect.MakeMap(e.Type())) | ||||
| @@ -154,12 +267,12 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value) error { | ||||
| 			numOfElements := randQty % maxElements | ||||
| 			for i := 0; i < numOfElements; i++ { | ||||
| 				key := reflect.New(e.Type().Key()).Elem() | ||||
| 				err := f.fuzzStruct(key) | ||||
| 				err := f.fuzzStruct(key, customFunctions) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				val := reflect.New(e.Type().Elem()).Elem() | ||||
| 				err = f.fuzzStruct(val) | ||||
| 				err = f.fuzzStruct(val, customFunctions) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| @@ -169,7 +282,7 @@ func (f *ConsumeFuzzer) fuzzStruct(e reflect.Value) error { | ||||
| 	case reflect.Ptr: | ||||
| 		if e.CanSet() { | ||||
| 			e.Set(reflect.New(e.Type().Elem())) | ||||
| 			err := f.fuzzStruct(e.Elem()) | ||||
| 			err := f.fuzzStruct(e.Elem(), customFunctions) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| @@ -238,6 +351,75 @@ func (f *ConsumeFuzzer) GetByte() (byte, error) { | ||||
| 	return returnByte, nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetNBytes(numberOfBytes int) ([]byte, error) { | ||||
| 	returnBytes := make([]byte, 0) | ||||
| 	if len(f.data) == 0 { | ||||
| 		return returnBytes, errors.New("Not enough bytes to get byte") | ||||
| 	} | ||||
| 	if f.position >= len(f.data) { | ||||
| 		return returnBytes, errors.New("Not enough bytes to get byte") | ||||
| 	} | ||||
| 	for i := 0; i < numberOfBytes; i++ { | ||||
| 		newByte, err := f.GetByte() | ||||
| 		if err != nil { | ||||
| 			return returnBytes, err | ||||
| 		} | ||||
| 		returnBytes = append(returnBytes, newByte) | ||||
| 	} | ||||
| 	return returnBytes, nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetUint16() (uint16, error) { | ||||
| 	u16, err := f.GetNBytes(2) | ||||
| 	if err != nil { | ||||
| 		return uint16(0), err | ||||
| 	} | ||||
| 	littleEndian, err := f.GetBool() | ||||
| 	if err != nil { | ||||
| 		return uint16(0), err | ||||
| 	} | ||||
| 	if littleEndian { | ||||
| 		u16LE := binary.LittleEndian.Uint16(u16) | ||||
| 		return u16LE, nil | ||||
| 	} | ||||
| 	u16BE := binary.BigEndian.Uint16(u16) | ||||
| 	return u16BE, nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetUint32() (uint32, error) { | ||||
| 	u32, err := f.GetNBytes(4) | ||||
| 	if err != nil { | ||||
| 		return uint32(0), err | ||||
| 	} | ||||
| 	littleEndian, err := f.GetBool() | ||||
| 	if err != nil { | ||||
| 		return uint32(0), err | ||||
| 	} | ||||
| 	if littleEndian { | ||||
| 		u32LE := binary.LittleEndian.Uint32(u32) | ||||
| 		return u32LE, nil | ||||
| 	} | ||||
| 	u32BE := binary.BigEndian.Uint32(u32) | ||||
| 	return u32BE, nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetUint64() (uint64, error) { | ||||
| 	u64, err := f.GetNBytes(8) | ||||
| 	if err != nil { | ||||
| 		return uint64(0), err | ||||
| 	} | ||||
| 	littleEndian, err := f.GetBool() | ||||
| 	if err != nil { | ||||
| 		return uint64(0), err | ||||
| 	} | ||||
| 	if littleEndian { | ||||
| 		u64LE := binary.LittleEndian.Uint64(u64) | ||||
| 		return u64LE, nil | ||||
| 	} | ||||
| 	u64BE := binary.BigEndian.Uint64(u64) | ||||
| 	return u64BE, nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetBytes() ([]byte, error) { | ||||
| 	if len(f.data) == 0 || f.position >= len(f.data) { | ||||
| 		return nil, errors.New("Not enough bytes to create byte array") | ||||
| @@ -296,7 +478,7 @@ func (f *ConsumeFuzzer) FuzzMap(m interface{}) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // TarBytes returns valid tar bytes for a tar archive | ||||
| // TarBytes returns valid bytes for a tar archive | ||||
| func (f *ConsumeFuzzer) TarBytes() ([]byte, error) { | ||||
| 	var buf bytes.Buffer | ||||
| 	tw := tar.NewWriter(&buf) | ||||
| @@ -334,6 +516,178 @@ func (f *ConsumeFuzzer) TarBytes() ([]byte, error) { | ||||
| 	if err := tw.Close(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	//fmt.Println(string(buf.Bytes())) | ||||
| 	return buf.Bytes(), nil | ||||
| } | ||||
|  | ||||
| // Creates pseudo-random files in rootDir. | ||||
| // Will create subdirs and place the files there. | ||||
| // It is the callers responsibility to ensure that | ||||
| // rootDir exists. | ||||
| func (f *ConsumeFuzzer) CreateFiles(rootDir string) error { | ||||
| 	var noOfCreatedFiles int | ||||
| 	noOfCreatedFiles = 0 | ||||
| 	numberOfFiles, err := f.GetInt() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	maxNumberOfFiles := numberOfFiles % 4000 // This is completely arbitrary | ||||
| 	if maxNumberOfFiles == 0 { | ||||
| 		return errors.New("maxNumberOfFiles is nil") | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < maxNumberOfFiles; i++ { | ||||
| 		// The file to create: | ||||
| 		fileName, err := f.GetString() | ||||
| 		if err != nil { | ||||
| 			if noOfCreatedFiles > 0 { | ||||
| 				// If files have been created, we don't return | ||||
| 				// an error | ||||
| 				break | ||||
| 			} else { | ||||
| 				return errors.New("Could not get fileName") | ||||
| 			} | ||||
| 		} | ||||
| 		var fullFilePath string | ||||
| 		fullFilePath, err = securejoin.SecureJoin(rootDir, fileName) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		// Find the subdirectory of the file | ||||
| 		subDir := filepath.Dir(fileName) | ||||
| 		if subDir != "" && subDir != "." { | ||||
| 			// create the dir first | ||||
|  | ||||
| 			// Avoid going outside the root dir | ||||
| 			if strings.Contains(subDir, "../") || (len(subDir) > 0 && subDir[0] == 47) || strings.Contains(subDir, "\\") { | ||||
| 				continue | ||||
| 			} | ||||
| 			dirPath := filepath.Join(rootDir, subDir) | ||||
| 			dirPath, err := securejoin.SecureJoin(rootDir, subDir) | ||||
| 			if err != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 			if _, err := os.Stat(dirPath); os.IsNotExist(err) { | ||||
| 				err2 := os.MkdirAll(dirPath, 0777) | ||||
| 				if err2 != nil { | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			fullFilePath, err = securejoin.SecureJoin(dirPath, fileName) | ||||
| 			if err != nil { | ||||
| 				continue | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Create symlink | ||||
| 			createSymlink, err := f.GetBool() | ||||
| 			if err != nil { | ||||
| 				if noOfCreatedFiles > 0 { | ||||
| 					break | ||||
| 				} else { | ||||
| 					return errors.New("Could not create the symlink") | ||||
| 				} | ||||
| 			} | ||||
| 			if createSymlink { | ||||
| 				symlinkTarget, err := f.GetString() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				os.Symlink(symlinkTarget, fullFilePath) | ||||
| 				// stop loop here, since a symlink needs no further action | ||||
| 				noOfCreatedFiles++ | ||||
| 				continue | ||||
| 			} | ||||
| 			// We create a normal file | ||||
| 			fileContents, err := f.GetBytes() | ||||
| 			if err != nil { | ||||
| 				if noOfCreatedFiles > 0 { | ||||
| 					break | ||||
| 				} else { | ||||
| 					return errors.New("Could not create the file") | ||||
| 				} | ||||
| 			} | ||||
| 			createdFile, err := os.Create(fullFilePath) | ||||
| 			if err != nil { | ||||
| 				createdFile.Close() | ||||
| 				continue | ||||
| 			} | ||||
| 			_, err = createdFile.Write(fileContents) | ||||
| 			if err != nil { | ||||
| 				createdFile.Close() | ||||
| 				continue | ||||
| 			} | ||||
| 			createdFile.Close() | ||||
| 			noOfCreatedFiles++ | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Returns a string that can only consists of characters that are | ||||
| // included in possibleChars. Will return an error if the created | ||||
| // string does not have the specified length | ||||
| func (f *ConsumeFuzzer) GetStringFrom(possibleChars string, length int) (string, error) { | ||||
| 	returnString := "" | ||||
| 	if (len(f.data) - f.position) < length { | ||||
| 		return returnString, errors.New("Not enough bytes to create a string") | ||||
| 	} | ||||
| 	for i := 0; i < length; i++ { | ||||
| 		charIndex, err := f.GetInt() | ||||
| 		if err != nil { | ||||
| 			return returnString, err | ||||
| 		} | ||||
| 		charToAdd := string(possibleChars[charIndex%len(possibleChars)]) | ||||
| 		returnString = fmt.Sprintf(returnString + charToAdd) | ||||
| 	} | ||||
| 	return returnString, nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetRune() ([]rune, error) { | ||||
| 	stringToConvert, err := f.GetString() | ||||
| 	if err != nil { | ||||
| 		return []rune("nil"), err | ||||
| 	} | ||||
| 	return []rune(stringToConvert), nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetFloat32() (float32, error) { | ||||
| 	u32, err := f.GetNBytes(4) | ||||
| 	if err != nil { | ||||
| 		return float32(0.0), err | ||||
| 	} | ||||
| 	littleEndian, err := f.GetBool() | ||||
| 	if err != nil { | ||||
| 		return float32(0.0), err | ||||
| 	} | ||||
| 	if littleEndian { | ||||
| 		u32LE := binary.LittleEndian.Uint32(u32) | ||||
| 		return math.Float32frombits(u32LE), nil | ||||
| 	} | ||||
| 	u32BE := binary.BigEndian.Uint32(u32) | ||||
| 	return math.Float32frombits(u32BE), nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GetFloat64() (float64, error) { | ||||
| 	u64, err := f.GetNBytes(8) | ||||
| 	if err != nil { | ||||
| 		return float64(0.0), err | ||||
| 	} | ||||
| 	littleEndian, err := f.GetBool() | ||||
| 	if err != nil { | ||||
| 		return float64(0.0), err | ||||
| 	} | ||||
| 	if littleEndian { | ||||
| 		u64LE := binary.LittleEndian.Uint64(u64) | ||||
| 		return math.Float64frombits(u64LE), nil | ||||
| 	} | ||||
| 	u64BE := binary.BigEndian.Uint64(u64) | ||||
| 	return math.Float64frombits(u64BE), nil | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) CreateSlice(targetSlice interface{}) error { | ||||
| 	err := f.GenerateStruct(targetSlice) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
							
								
								
									
										57
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/funcs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/funcs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| package gofuzzheaders | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"reflect" | ||||
| ) | ||||
|  | ||||
| type Continue struct { | ||||
| 	F *ConsumeFuzzer | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) AddFuncs(fuzzFuncs []interface{}) { | ||||
| 	for i := range fuzzFuncs { | ||||
| 		v := reflect.ValueOf(fuzzFuncs[i]) | ||||
| 		if v.Kind() != reflect.Func { | ||||
| 			panic("Need only funcs!") | ||||
| 		} | ||||
| 		t := v.Type() | ||||
| 		if t.NumIn() != 2 || t.NumOut() != 1 { | ||||
| 			fmt.Println(t.NumIn(), t.NumOut()) | ||||
|  | ||||
| 			panic("Need 2 in and 1 out params. In must be the type. Out must be an error") | ||||
| 		} | ||||
| 		argT := t.In(0) | ||||
| 		switch argT.Kind() { | ||||
| 		case reflect.Ptr, reflect.Map: | ||||
| 		default: | ||||
| 			panic("fuzzFunc must take pointer or map type") | ||||
| 		} | ||||
| 		if t.In(1) != reflect.TypeOf(Continue{}) { | ||||
| 			panic("fuzzFunc's second parameter must be type Continue") | ||||
| 		} | ||||
| 		f.Funcs[argT] = v | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (f *ConsumeFuzzer) GenerateWithCustom(targetStruct interface{}) error { | ||||
| 	v := reflect.ValueOf(targetStruct) | ||||
| 	e := v.Elem() | ||||
| 	return f.fuzzStruct(e, true) | ||||
| } | ||||
|  | ||||
| func (c Continue) GenerateStruct(targetStruct interface{}) error { | ||||
| 	err := c.F.GenerateStruct(targetStruct) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (c Continue) GenerateStructWithCustom(targetStruct interface{}) error { | ||||
| 	err := c.F.GenerateWithCustom(targetStruct) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										524
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/sql.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										524
									
								
								vendor/github.com/AdaLogics/go-fuzz-headers/sql.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,524 @@ | ||||
| package gofuzzheaders | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // returns a keyword by index | ||||
| func getKeyword(f *ConsumeFuzzer) (string, error) { | ||||
| 	index, err := f.GetInt() | ||||
| 	if err != nil { | ||||
| 		return keywords[0], err | ||||
| 	} | ||||
| 	for i, k := range keywords { | ||||
| 		if i == index { | ||||
| 			return k, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return keywords[0], fmt.Errorf("Could not get a kw") | ||||
| } | ||||
|  | ||||
| // Simple utility function to check if a string | ||||
| // slice contains a string. | ||||
| func containsString(s []string, e string) bool { | ||||
| 	for _, a := range s { | ||||
| 		if a == e { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // These keywords are used specifically for fuzzing Vitess | ||||
| var keywords = []string{ | ||||
| 	"accessible", "action", "add", "after", "against", "algorithm", | ||||
| 	"all", "alter", "always", "analyze", "and", "as", "asc", "asensitive", | ||||
| 	"auto_increment", "avg_row_length", "before", "begin", "between", | ||||
| 	"bigint", "binary", "_binary", "_utf8mb4", "_utf8", "_latin1", "bit", | ||||
| 	"blob", "bool", "boolean", "both", "by", "call", "cancel", "cascade", | ||||
| 	"cascaded", "case", "cast", "channel", "change", "char", "character", | ||||
| 	"charset", "check", "checksum", "coalesce", "code", "collate", "collation", | ||||
| 	"column", "columns", "comment", "committed", "commit", "compact", "complete", | ||||
| 	"compressed", "compression", "condition", "connection", "constraint", "continue", | ||||
| 	"convert", "copy", "cume_dist", "substr", "substring", "create", "cross", | ||||
| 	"csv", "current_date", "current_time", "current_timestamp", "current_user", | ||||
| 	"cursor", "data", "database", "databases", "day", "day_hour", "day_microsecond", | ||||
| 	"day_minute", "day_second", "date", "datetime", "dec", "decimal", "declare", | ||||
| 	"default", "definer", "delay_key_write", "delayed", "delete", "dense_rank", | ||||
| 	"desc", "describe", "deterministic", "directory", "disable", "discard", | ||||
| 	"disk", "distinct", "distinctrow", "div", "double", "do", "drop", "dumpfile", | ||||
| 	"duplicate", "dynamic", "each", "else", "elseif", "empty", "enable", | ||||
| 	"enclosed", "encryption", "end", "enforced", "engine", "engines", "enum", | ||||
| 	"error", "escape", "escaped", "event", "exchange", "exclusive", "exists", | ||||
| 	"exit", "explain", "expansion", "export", "extended", "extract", "false", | ||||
| 	"fetch", "fields", "first", "first_value", "fixed", "float", "float4", | ||||
| 	"float8", "flush", "for", "force", "foreign", "format", "from", "full", | ||||
| 	"fulltext", "function", "general", "generated", "geometry", "geometrycollection", | ||||
| 	"get", "global", "gtid_executed", "grant", "group", "grouping", "groups", | ||||
| 	"group_concat", "having", "header", "high_priority", "hosts", "hour", "hour_microsecond", | ||||
| 	"hour_minute", "hour_second", "if", "ignore", "import", "in", "index", "indexes", | ||||
| 	"infile", "inout", "inner", "inplace", "insensitive", "insert", "insert_method", | ||||
| 	"int", "int1", "int2", "int3", "int4", "int8", "integer", "interval", | ||||
| 	"into", "io_after_gtids", "is", "isolation", "iterate", "invoker", "join", | ||||
| 	"json", "json_table", "key", "keys", "keyspaces", "key_block_size", "kill", "lag", | ||||
| 	"language", "last", "last_value", "last_insert_id", "lateral", "lead", "leading", | ||||
| 	"leave", "left", "less", "level", "like", "limit", "linear", "lines", | ||||
| 	"linestring", "load", "local", "localtime", "localtimestamp", "lock", "logs", | ||||
| 	"long", "longblob", "longtext", "loop", "low_priority", "manifest", | ||||
| 	"master_bind", "match", "max_rows", "maxvalue", "mediumblob", "mediumint", | ||||
| 	"mediumtext", "memory", "merge", "microsecond", "middleint", "min_rows", "minute", | ||||
| 	"minute_microsecond", "minute_second", "mod", "mode", "modify", "modifies", | ||||
| 	"multilinestring", "multipoint", "multipolygon", "month", "name", | ||||
| 	"names", "natural", "nchar", "next", "no", "none", "not", "no_write_to_binlog", | ||||
| 	"nth_value", "ntile", "null", "numeric", "of", "off", "offset", "on", | ||||
| 	"only", "open", "optimize", "optimizer_costs", "option", "optionally", | ||||
| 	"or", "order", "out", "outer", "outfile", "over", "overwrite", "pack_keys", | ||||
| 	"parser", "partition", "partitioning", "password", "percent_rank", "plugins", | ||||
| 	"point", "polygon", "precision", "primary", "privileges", "processlist", | ||||
| 	"procedure", "query", "quarter", "range", "rank", "read", "reads", "read_write", | ||||
| 	"real", "rebuild", "recursive", "redundant", "references", "regexp", "relay", | ||||
| 	"release", "remove", "rename", "reorganize", "repair", "repeat", "repeatable", | ||||
| 	"replace", "require", "resignal", "restrict", "return", "retry", "revert", | ||||
| 	"revoke", "right", "rlike", "rollback", "row", "row_format", "row_number", | ||||
| 	"rows", "s3", "savepoint", "schema", "schemas", "second", "second_microsecond", | ||||
| 	"security", "select", "sensitive", "separator", "sequence", "serializable", | ||||
| 	"session", "set", "share", "shared", "show", "signal", "signed", "slow", | ||||
| 	"smallint", "spatial", "specific", "sql", "sqlexception", "sqlstate", | ||||
| 	"sqlwarning", "sql_big_result", "sql_cache", "sql_calc_found_rows", | ||||
| 	"sql_no_cache", "sql_small_result", "ssl", "start", "starting", | ||||
| 	"stats_auto_recalc", "stats_persistent", "stats_sample_pages", "status", | ||||
| 	"storage", "stored", "straight_join", "stream", "system", "vstream", | ||||
| 	"table", "tables", "tablespace", "temporary", "temptable", "terminated", | ||||
| 	"text", "than", "then", "time", "timestamp", "timestampadd", "timestampdiff", | ||||
| 	"tinyblob", "tinyint", "tinytext", "to", "trailing", "transaction", "tree", | ||||
| 	"traditional", "trigger", "triggers", "true", "truncate", "uncommitted", | ||||
| 	"undefined", "undo", "union", "unique", "unlock", "unsigned", "update", | ||||
| 	"upgrade", "usage", "use", "user", "user_resources", "using", "utc_date", | ||||
| 	"utc_time", "utc_timestamp", "validation", "values", "variables", "varbinary", | ||||
| 	"varchar", "varcharacter", "varying", "vgtid_executed", "virtual", "vindex", | ||||
| 	"vindexes", "view", "vitess", "vitess_keyspaces", "vitess_metadata", | ||||
| 	"vitess_migration", "vitess_migrations", "vitess_replication_status", | ||||
| 	"vitess_shards", "vitess_tablets", "vschema", "warnings", "when", | ||||
| 	"where", "while", "window", "with", "without", "work", "write", "xor", | ||||
| 	"year", "year_month", "zerofill"} | ||||
|  | ||||
| // Keywords that could get an additional keyword | ||||
| var needCustomString = []string{ | ||||
| 	"DISTINCTROW", "FROM", // Select keywords: | ||||
| 	"GROUP BY", "HAVING", "WINDOW", | ||||
| 	"FOR", | ||||
| 	"ORDER BY", "LIMIT", | ||||
| 	"INTO", "PARTITION", "AS", // Insert Keywords: | ||||
| 	"ON DUPLICATE KEY UPDATE", | ||||
| 	"WHERE", "LIMIT", // Delete keywords | ||||
| 	"INFILE", "INTO TABLE", "CHARACTER SET", // Load keywords | ||||
| 	"TERMINATED BY", "ENCLOSED BY", | ||||
| 	"ESCAPED BY", "STARTING BY", | ||||
| 	"TERMINATED BY", "STARTING BY", | ||||
| 	"IGNORE", | ||||
| 	"VALUE", "VALUES", // Replace tokens | ||||
| 	"SET",                                   // Update tokens | ||||
| 	"ENGINE =",                              // Drop tokens | ||||
| 	"DEFINER =", "ON SCHEDULE", "RENAME TO", // Alter tokens | ||||
| 	"COMMENT", "DO", "INITIAL_SIZE = ", "OPTIONS", | ||||
| } | ||||
|  | ||||
| var alterTableTokens = [][]string{ | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"CUSTOM_ALTTER_TABLE_OPTIONS"}, | ||||
| 	{"PARTITION_OPTIONS_FOR_ALTER_TABLE"}, | ||||
| } | ||||
|  | ||||
| var alterTokens = [][]string{ | ||||
| 	{"DATABASE", "SCHEMA", "DEFINER = ", "EVENT", "FUNCTION", "INSTANCE", | ||||
| 		"LOGFILE GROUP", "PROCEDURE", "SERVER"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"ON SCHEDULE", "ON COMPLETION PRESERVE", "ON COMPLETION NOT PRESERVE", | ||||
| 		"ADD UNDOFILE", "OPTIONS"}, | ||||
| 	{"RENAME TO", "INITIAL_SIZE = "}, | ||||
| 	{"ENABLE", "DISABLE", "DISABLE ON SLAVE", "ENGINE"}, | ||||
| 	{"COMMENT"}, | ||||
| 	{"DO"}, | ||||
| } | ||||
|  | ||||
| var setTokens = [][]string{ | ||||
| 	{"CHARACTER SET", "CHARSET", "CUSTOM_FUZZ_STRING", "NAMES"}, | ||||
| 	{"CUSTOM_FUZZ_STRING", "DEFAULT", "="}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| } | ||||
|  | ||||
| var dropTokens = [][]string{ | ||||
| 	{"TEMPORARY", "UNDO"}, | ||||
| 	{"DATABASE", "SCHEMA", "EVENT", "INDEX", "LOGFILE GROUP", | ||||
| 		"PROCEDURE", "FUNCTION", "SERVER", "SPATIAL REFERENCE SYSTEM", | ||||
| 		"TABLE", "TABLESPACE", "TRIGGER", "VIEW"}, | ||||
| 	{"IF EXISTS"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"ON", "ENGINE = ", "RESTRICT", "CASCADE"}, | ||||
| } | ||||
|  | ||||
| var renameTokens = [][]string{ | ||||
| 	{"TABLE"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"TO"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| } | ||||
|  | ||||
| var truncateTokens = [][]string{ | ||||
| 	{"TABLE"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| } | ||||
|  | ||||
| var createTokens = [][]string{ | ||||
| 	{"OR REPLACE", "TEMPORARY", "UNDO"}, // For create spatial reference system | ||||
| 	{"UNIQUE", "FULLTEXT", "SPATIAL", "ALGORITHM = UNDEFINED", "ALGORITHM = MERGE", | ||||
| 		"ALGORITHM = TEMPTABLE"}, | ||||
| 	{"DATABASE", "SCHEMA", "EVENT", "FUNCTION", "INDEX", "LOGFILE GROUP", | ||||
| 		"PROCEDURE", "SERVER", "SPATIAL REFERENCE SYSTEM", "TABLE", "TABLESPACE", | ||||
| 		"TRIGGER", "VIEW"}, | ||||
| 	{"IF NOT EXISTS"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| } | ||||
|  | ||||
| var updateTokens = [][]string{ | ||||
| 	{"LOW_PRIORITY"}, | ||||
| 	{"IGNORE"}, | ||||
| 	{"SET"}, | ||||
| 	{"WHERE"}, | ||||
| 	{"ORDER BY"}, | ||||
| 	{"LIMIT"}, | ||||
| } | ||||
| var replaceTokens = [][]string{ | ||||
| 	{"LOW_PRIORITY", "DELAYED"}, | ||||
| 	{"INTO"}, | ||||
| 	{"PARTITION"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"VALUES", "VALUE"}, | ||||
| } | ||||
| var loadTokens = [][]string{ | ||||
| 	{"DATA"}, | ||||
| 	{"LOW_PRIORITY", "CONCURRENT", "LOCAL"}, | ||||
| 	{"INFILE"}, | ||||
| 	{"REPLACE", "IGNORE"}, | ||||
| 	{"INTO TABLE"}, | ||||
| 	{"PARTITION"}, | ||||
| 	{"CHARACTER SET"}, | ||||
| 	{"FIELDS", "COLUMNS"}, | ||||
| 	{"TERMINATED BY"}, | ||||
| 	{"OPTIONALLY"}, | ||||
| 	{"ENCLOSED BY"}, | ||||
| 	{"ESCAPED BY"}, | ||||
| 	{"LINES"}, | ||||
| 	{"STARTING BY"}, | ||||
| 	{"TERMINATED BY"}, | ||||
| 	{"IGNORE"}, | ||||
| 	{"LINES", "ROWS"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| } | ||||
|  | ||||
| // These Are everything that comes after "INSERT" | ||||
| var insertTokens = [][]string{ | ||||
| 	{"LOW_PRIORITY", "DELAYED", "HIGH_PRIORITY", "IGNORE"}, | ||||
| 	{"INTO"}, | ||||
| 	{"PARTITION"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"AS"}, | ||||
| 	{"ON DUPLICATE KEY UPDATE"}, | ||||
| } | ||||
|  | ||||
| // These are everything that comes after "SELECT" | ||||
| var selectTokens = [][]string{ | ||||
| 	{"*", "CUSTOM_FUZZ_STRING", "DISTINCTROW"}, | ||||
| 	{"HIGH_PRIORITY"}, | ||||
| 	{"STRAIGHT_JOIN"}, | ||||
| 	{"SQL_SMALL_RESULT", "SQL_BIG_RESULT", "SQL_BUFFER_RESULT"}, | ||||
| 	{"SQL_NO_CACHE", "SQL_CALC_FOUND_ROWS"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"FROM"}, | ||||
| 	{"WHERE"}, | ||||
| 	{"GROUP BY"}, | ||||
| 	{"HAVING"}, | ||||
| 	{"WINDOW"}, | ||||
| 	{"ORDER BY"}, | ||||
| 	{"LIMIT"}, | ||||
| 	{"CUSTOM_FUZZ_STRING"}, | ||||
| 	{"FOR"}, | ||||
| } | ||||
|  | ||||
| // These are everything that comes after "DELETE" | ||||
| var deleteTokens = [][]string{ | ||||
| 	{"LOW_PRIORITY", "QUICK", "IGNORE", "FROM", "AS"}, | ||||
| 	{"PARTITION"}, | ||||
| 	{"WHERE"}, | ||||
| 	{"ORDER BY"}, | ||||
| 	{"LIMIT"}, | ||||
| } | ||||
|  | ||||
| var alter_table_options = []string{ | ||||
| 	"ADD", "COLUMN", "FIRST", "AFTER", "INDEX", "KEY", "FULLTEXT", "SPATIAL", | ||||
| 	"CONSTRAINT", "UNIQUE", "FOREIGN KEY", "CHECK", "ENFORCED", "DROP", "ALTER", | ||||
| 	"NOT", "INPLACE", "COPY", "SET", "VISIBLE", "INVISIBLE", "DEFAULT", "CHANGE", | ||||
| 	"CHARACTER SET", "COLLATE", "DISABLE", "ENABLE", "KEYS", "TABLESPACE", "LOCK", | ||||
| 	"FORCE", "MODIFY", "SHARED", "EXCLUSIVE", "NONE", "ORDER BY", "RENAME COLUMN", | ||||
| 	"AS", "=", "ASC", "DESC", "WITH", "WITHOUT", "VALIDATION", "ADD PARTITION", | ||||
| 	"DROP PARTITION", "DISCARD PARTITION", "IMPORT PARTITION", "TRUNCATE PARTITION", | ||||
| 	"COALESCE PARTITION", "REORGANIZE PARTITION", "EXCHANGE PARTITION", | ||||
| 	"ANALYZE PARTITION", "CHECK PARTITION", "OPTIMIZE PARTITION", "REBUILD PARTITION", | ||||
| 	"REPAIR PARTITION", "REMOVE PARTITIONING", "USING", "BTREE", "HASH", "COMMENT", | ||||
| 	"KEY_BLOCK_SIZE", "WITH PARSER", "AUTOEXTEND_SIZE", "AUTO_INCREMENT", "AVG_ROW_LENGTH", | ||||
| 	"CHECKSUM", "INSERT_METHOD", "ROW_FORMAT", "DYNAMIC", "FIXED", "COMPRESSED", "REDUNDANT", | ||||
| 	"COMPACT", "SECONDARY_ENGINE_ATTRIBUTE", "STATS_AUTO_RECALC", "STATS_PERSISTENT", | ||||
| 	"STATS_SAMPLE_PAGES", "ZLIB", "LZ4", "ENGINE_ATTRIBUTE", "KEY_BLOCK_SIZE", "MAX_ROWS", | ||||
| 	"MIN_ROWS", "PACK_KEYS", "PASSWORD", "COMPRESSION", "CONNECTION", "DIRECTORY", | ||||
| 	"DELAY_KEY_WRITE", "ENCRYPTION", "STORAGE", "DISK", "MEMORY", "UNION"} | ||||
|  | ||||
| // Creates an 'alter table' statement. 'alter table' is an exception | ||||
| // in that it has its own function. The majority of statements | ||||
| // are created by 'createStmt()'. | ||||
| func createAlterTableStmt(f *ConsumeFuzzer) (string, error) { | ||||
| 	var stmt strings.Builder | ||||
| 	stmt.WriteString("ALTER TABLE ") | ||||
| 	maxArgs, err := f.GetInt() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	maxArgs = maxArgs % 30 | ||||
| 	if maxArgs == 0 { | ||||
| 		return "", fmt.Errorf("Could not create alter table stmt") | ||||
| 	} | ||||
| 	for i := 0; i < maxArgs; i++ { | ||||
| 		// Calculate if we get existing token or custom string | ||||
| 		tokenType, err := f.GetInt() | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		if tokenType%4 == 1 { | ||||
| 			customString, err := f.GetString() | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 			stmt.WriteString(fmt.Sprintf(" %s", customString)) | ||||
| 		} else { | ||||
| 			tokenIndex, err := f.GetInt() | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 			stmt.WriteString(fmt.Sprintf(" %s", alter_table_options[tokenIndex%len(alter_table_options)])) | ||||
| 		} | ||||
| 	} | ||||
| 	return stmt.String(), nil | ||||
| } | ||||
|  | ||||
| func chooseToken(tokens []string, f *ConsumeFuzzer) (string, error) { | ||||
| 	index, err := f.GetInt() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	var token strings.Builder | ||||
| 	token.WriteString(fmt.Sprintf(" %s", tokens[index%len(tokens)])) | ||||
| 	if token.String() == "CUSTOM_FUZZ_STRING" { | ||||
| 		customFuzzString, err := f.GetString() | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return customFuzzString, nil | ||||
| 	} | ||||
|  | ||||
| 	// Check if token requires an argument | ||||
| 	if containsString(needCustomString, token.String()) { | ||||
| 		customFuzzString, err := f.GetString() | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		token.WriteString(fmt.Sprintf(" %s", customFuzzString)) | ||||
| 	} | ||||
| 	return token.String(), nil | ||||
| } | ||||
|  | ||||
| var stmtTypes = map[string][][]string{ | ||||
| 	"DELETE":      deleteTokens, | ||||
| 	"INSERT":      insertTokens, | ||||
| 	"SELECT":      selectTokens, | ||||
| 	"LOAD":        loadTokens, | ||||
| 	"REPLACE":     replaceTokens, | ||||
| 	"CREATE":      createTokens, | ||||
| 	"DROP":        dropTokens, | ||||
| 	"RENAME":      renameTokens, | ||||
| 	"TRUNCATE":    truncateTokens, | ||||
| 	"SET":         setTokens, | ||||
| 	"ALTER":       alterTokens, | ||||
| 	"ALTER TABLE": alterTableTokens, // ALTER TABLE has its own set of tokens | ||||
| } | ||||
|  | ||||
| var stmtTypeEnum = map[int]string{ | ||||
| 	0:  "DELETE", | ||||
| 	1:  "INSERT", | ||||
| 	2:  "SELECT", | ||||
| 	3:  "LOAD", | ||||
| 	4:  "REPLACE", | ||||
| 	5:  "CREATE", | ||||
| 	6:  "DROP", | ||||
| 	7:  "RENAME", | ||||
| 	8:  "TRUNCATE", | ||||
| 	9:  "SET", | ||||
| 	10: "ALTER", | ||||
| 	11: "ALTER TABLE", | ||||
| } | ||||
|  | ||||
| func createStmt(f *ConsumeFuzzer) (string, error) { | ||||
| 	stmtIndex, err := f.GetInt() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	stmtIndex = stmtIndex % len(stmtTypes) | ||||
|  | ||||
| 	queryType := stmtTypeEnum[stmtIndex] | ||||
| 	tokens := stmtTypes[queryType] | ||||
|  | ||||
| 	// We have custom creator for ALTER TABLE | ||||
| 	if queryType == "ALTER TABLE" { | ||||
| 		query, err := createAlterTableStmt(f) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		return query, nil | ||||
| 	} | ||||
|  | ||||
| 	// Here we are creating a query that is not | ||||
| 	// an 'alter table' query. For available | ||||
| 	// queries, see "stmtTypes" | ||||
|  | ||||
| 	// First specify the first query keyword: | ||||
| 	var query strings.Builder | ||||
| 	query.WriteString(queryType) | ||||
|  | ||||
| 	// Next create the args for the | ||||
| 	queryArgs, err := createStmtArgs(tokens, f) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	query.WriteString(fmt.Sprintf(" %s", queryArgs)) | ||||
| 	return query.String(), nil | ||||
| } | ||||
|  | ||||
| // Creates the arguments of a statements. In a select statement | ||||
| // that would be everything after "select". | ||||
| func createStmtArgs(tokenslice [][]string, f *ConsumeFuzzer) (string, error) { | ||||
| 	var query strings.Builder | ||||
| 	var token strings.Builder | ||||
|  | ||||
| 	// We go through the tokens in the tokenslice, | ||||
| 	// create the respective token and add it to | ||||
| 	// "query" | ||||
| 	for _, tokens := range tokenslice { | ||||
|  | ||||
| 		// For extra randomization, the fuzzer can | ||||
| 		// choose to not include this token. | ||||
| 		includeThisToken, err := f.GetBool() | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		if !includeThisToken { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// There may be several tokens to choose from: | ||||
| 		if len(tokens) > 1 { | ||||
| 			chosenToken, err := chooseToken(tokens, f) | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 			query.WriteString(fmt.Sprintf(" %s", chosenToken)) | ||||
| 		} else { | ||||
| 			token.WriteString(tokens[0]) | ||||
|  | ||||
| 			// In case the token is "CUSTOM_FUZZ_STRING" | ||||
| 			// we will then create a non-structured string | ||||
| 			if token.String() == "CUSTOM_FUZZ_STRING" { | ||||
| 				customFuzzString, err := f.GetString() | ||||
| 				if err != nil { | ||||
| 					return "", err | ||||
| 				} | ||||
| 				query.WriteString(fmt.Sprintf(" %s", customFuzzString)) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			// Check if token requires an argument. | ||||
| 			// Tokens that take an argument can be found | ||||
| 			// in 'needCustomString'. If so, we add a | ||||
| 			// non-structured string to the token. | ||||
| 			if containsString(needCustomString, token.String()) { | ||||
| 				customFuzzString, err := f.GetString() | ||||
| 				if err != nil { | ||||
| 					return "", err | ||||
| 				} | ||||
| 				token.WriteString(fmt.Sprintf(" %s", customFuzzString)) | ||||
| 			} | ||||
| 			query.WriteString(fmt.Sprintf(" %s", token.String())) | ||||
| 		} | ||||
| 	} | ||||
| 	return query.String(), nil | ||||
| } | ||||
|  | ||||
| // Creates a semi-structured query. It creates a string | ||||
| // that is a combination of the keywords and random strings. | ||||
| func createQuery(f *ConsumeFuzzer) (string, error) { | ||||
| 	queryLen, err := f.GetInt() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	maxLen := queryLen % 60 | ||||
| 	if maxLen == 0 { | ||||
| 		return "", fmt.Errorf("Could not create a query") | ||||
| 	} | ||||
| 	var query strings.Builder | ||||
| 	for i := 0; i < maxLen; i++ { | ||||
| 		// Get a new token: | ||||
| 		useKeyword, err := f.GetBool() | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		if useKeyword { | ||||
| 			keyword, err := getKeyword(f) | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 			query.WriteString(fmt.Sprintf(" %s", keyword)) | ||||
| 		} else { | ||||
| 			customString, err := f.GetString() | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| 			query.WriteString(fmt.Sprintf(" %s", customString)) | ||||
| 		} | ||||
| 	} | ||||
| 	if query.String() == "" { | ||||
| 		return "", fmt.Errorf("Could not create a query") | ||||
| 	} | ||||
| 	return query.String(), nil | ||||
| } | ||||
|  | ||||
| // This is the API that users will interact with. | ||||
| // Usage: | ||||
| // f := NewConsumer(data) | ||||
| // sqlString, err := f.GetSQLString() | ||||
| func (f *ConsumeFuzzer) GetSQLString() (string, error) { | ||||
| 	var query string | ||||
| 	veryStructured, err := f.GetBool() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	if veryStructured { | ||||
| 		query, err = createStmt(f) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 	} else { | ||||
| 		query, err = createQuery(f) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 	} | ||||
| 	return query, nil | ||||
| } | ||||
							
								
								
									
										21
									
								
								vendor/github.com/cyphar/filepath-securejoin/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/cyphar/filepath-securejoin/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| # Copyright (C) 2017 SUSE LLC. All rights reserved. | ||||
| # Use of this source code is governed by a BSD-style | ||||
| # license that can be found in the LICENSE file. | ||||
|  | ||||
| language: go | ||||
| go: | ||||
|     - 1.13.x | ||||
|     - 1.16.x | ||||
|     - tip | ||||
| arch: | ||||
|     - AMD64 | ||||
|     - ppc64le | ||||
| os: | ||||
|     - linux | ||||
|     - osx | ||||
|  | ||||
| script: | ||||
|     - go test -cover -v ./... | ||||
|  | ||||
| notifications: | ||||
|     email: false | ||||
							
								
								
									
										28
									
								
								vendor/github.com/cyphar/filepath-securejoin/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/github.com/cyphar/filepath-securejoin/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. | ||||
| Copyright (C) 2017 SUSE LLC. All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are | ||||
| met: | ||||
|  | ||||
|    * Redistributions of source code must retain the above copyright | ||||
| notice, this list of conditions and the following disclaimer. | ||||
|    * Redistributions in binary form must reproduce the above | ||||
| copyright notice, this list of conditions and the following disclaimer | ||||
| in the documentation and/or other materials provided with the | ||||
| distribution. | ||||
|    * Neither the name of Google Inc. nor the names of its | ||||
| contributors may be used to endorse or promote products derived from | ||||
| this software without specific prior written permission. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										79
									
								
								vendor/github.com/cyphar/filepath-securejoin/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								vendor/github.com/cyphar/filepath-securejoin/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| ## `filepath-securejoin` ## | ||||
|  | ||||
| [](https://travis-ci.org/cyphar/filepath-securejoin) | ||||
|  | ||||
| An implementation of `SecureJoin`, a [candidate for inclusion in the Go | ||||
| standard library][go#20126]. The purpose of this function is to be a "secure" | ||||
| alternative to `filepath.Join`, and in particular it provides certain | ||||
| guarantees that are not provided by `filepath.Join`. | ||||
|  | ||||
| > **NOTE**: This code is *only* safe if you are not at risk of other processes | ||||
| > modifying path components after you've used `SecureJoin`. If it is possible | ||||
| > for a malicious process to modify path components of the resolved path, then | ||||
| > you will be vulnerable to some fairly trivial TOCTOU race conditions. [There | ||||
| > are some Linux kernel patches I'm working on which might allow for a better | ||||
| > solution.][lwn-obeneath] | ||||
| > | ||||
| > In addition, with a slightly modified API it might be possible to use | ||||
| > `O_PATH` and verify that the opened path is actually the resolved one -- but | ||||
| > I have not done that yet. I might add it in the future as a helper function | ||||
| > to help users verify the path (we can't just return `/proc/self/fd/<foo>` | ||||
| > because that doesn't always work transparently for all users). | ||||
|  | ||||
| This is the function prototype: | ||||
|  | ||||
| ```go | ||||
| func SecureJoin(root, unsafePath string) (string, error) | ||||
| ``` | ||||
|  | ||||
| This library **guarantees** the following: | ||||
|  | ||||
| * If no error is set, the resulting string **must** be a child path of | ||||
|   `root` and will not contain any symlink path components (they will all be | ||||
|   expanded). | ||||
|  | ||||
| * When expanding symlinks, all symlink path components **must** be resolved | ||||
|   relative to the provided root. In particular, this can be considered a | ||||
|   userspace implementation of how `chroot(2)` operates on file paths. Note that | ||||
|   these symlinks will **not** be expanded lexically (`filepath.Clean` is not | ||||
|   called on the input before processing). | ||||
|  | ||||
| * Non-existent path components are unaffected by `SecureJoin` (similar to | ||||
|   `filepath.EvalSymlinks`'s semantics). | ||||
|  | ||||
| * The returned path will always be `filepath.Clean`ed and thus not contain any | ||||
|   `..` components. | ||||
|  | ||||
| A (trivial) implementation of this function on GNU/Linux systems could be done | ||||
| with the following (note that this requires root privileges and is far more | ||||
| opaque than the implementation in this library, and also requires that | ||||
| `readlink` is inside the `root` path): | ||||
|  | ||||
| ```go | ||||
| package securejoin | ||||
|  | ||||
| import ( | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| ) | ||||
|  | ||||
| func SecureJoin(root, unsafePath string) (string, error) { | ||||
| 	unsafePath = string(filepath.Separator) + unsafePath | ||||
| 	cmd := exec.Command("chroot", root, | ||||
| 		"readlink", "--canonicalize-missing", "--no-newline", unsafePath) | ||||
| 	output, err := cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	expanded := string(output) | ||||
| 	return filepath.Join(root, expanded), nil | ||||
| } | ||||
| ``` | ||||
|  | ||||
| [lwn-obeneath]: https://lwn.net/Articles/767547/ | ||||
| [go#20126]: https://github.com/golang/go/issues/20126 | ||||
|  | ||||
| ### License ### | ||||
|  | ||||
| The license of this project is the same as Go, which is a BSD 3-clause license | ||||
| available in the `LICENSE` file. | ||||
							
								
								
									
										1
									
								
								vendor/github.com/cyphar/filepath-securejoin/VERSION
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/cyphar/filepath-securejoin/VERSION
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| 0.2.3 | ||||
							
								
								
									
										115
									
								
								vendor/github.com/cyphar/filepath-securejoin/join.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								vendor/github.com/cyphar/filepath-securejoin/join.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| // Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved. | ||||
| // Copyright (C) 2017 SUSE LLC. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| // Package securejoin is an implementation of the hopefully-soon-to-be-included | ||||
| // SecureJoin helper that is meant to be part of the "path/filepath" package. | ||||
| // The purpose of this project is to provide a PoC implementation to make the | ||||
| // SecureJoin proposal (https://github.com/golang/go/issues/20126) more | ||||
| // tangible. | ||||
| package securejoin | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"errors" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| // IsNotExist tells you if err is an error that implies that either the path | ||||
| // accessed does not exist (or path components don't exist). This is | ||||
| // effectively a more broad version of os.IsNotExist. | ||||
| func IsNotExist(err error) bool { | ||||
| 	// Check that it's not actually an ENOTDIR, which in some cases is a more | ||||
| 	// convoluted case of ENOENT (usually involving weird paths). | ||||
| 	return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT) | ||||
| } | ||||
|  | ||||
| // SecureJoinVFS joins the two given path components (similar to Join) except | ||||
| // that the returned path is guaranteed to be scoped inside the provided root | ||||
| // path (when evaluated). Any symbolic links in the path are evaluated with the | ||||
| // given root treated as the root of the filesystem, similar to a chroot. The | ||||
| // filesystem state is evaluated through the given VFS interface (if nil, the | ||||
| // standard os.* family of functions are used). | ||||
| // | ||||
| // Note that the guarantees provided by this function only apply if the path | ||||
| // components in the returned string are not modified (in other words are not | ||||
| // replaced with symlinks on the filesystem) after this function has returned. | ||||
| // Such a symlink race is necessarily out-of-scope of SecureJoin. | ||||
| func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) { | ||||
| 	// Use the os.* VFS implementation if none was specified. | ||||
| 	if vfs == nil { | ||||
| 		vfs = osVFS{} | ||||
| 	} | ||||
|  | ||||
| 	var path bytes.Buffer | ||||
| 	n := 0 | ||||
| 	for unsafePath != "" { | ||||
| 		if n > 255 { | ||||
| 			return "", &os.PathError{Op: "SecureJoin", Path: root + "/" + unsafePath, Err: syscall.ELOOP} | ||||
| 		} | ||||
|  | ||||
| 		// Next path component, p. | ||||
| 		i := strings.IndexRune(unsafePath, filepath.Separator) | ||||
| 		var p string | ||||
| 		if i == -1 { | ||||
| 			p, unsafePath = unsafePath, "" | ||||
| 		} else { | ||||
| 			p, unsafePath = unsafePath[:i], unsafePath[i+1:] | ||||
| 		} | ||||
|  | ||||
| 		// Create a cleaned path, using the lexical semantics of /../a, to | ||||
| 		// create a "scoped" path component which can safely be joined to fullP | ||||
| 		// for evaluation. At this point, path.String() doesn't contain any | ||||
| 		// symlink components. | ||||
| 		cleanP := filepath.Clean(string(filepath.Separator) + path.String() + p) | ||||
| 		if cleanP == string(filepath.Separator) { | ||||
| 			path.Reset() | ||||
| 			continue | ||||
| 		} | ||||
| 		fullP := filepath.Clean(root + cleanP) | ||||
|  | ||||
| 		// Figure out whether the path is a symlink. | ||||
| 		fi, err := vfs.Lstat(fullP) | ||||
| 		if err != nil && !IsNotExist(err) { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		// Treat non-existent path components the same as non-symlinks (we | ||||
| 		// can't do any better here). | ||||
| 		if IsNotExist(err) || fi.Mode()&os.ModeSymlink == 0 { | ||||
| 			path.WriteString(p) | ||||
| 			path.WriteRune(filepath.Separator) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		// Only increment when we actually dereference a link. | ||||
| 		n++ | ||||
|  | ||||
| 		// It's a symlink, expand it by prepending it to the yet-unparsed path. | ||||
| 		dest, err := vfs.Readlink(fullP) | ||||
| 		if err != nil { | ||||
| 			return "", err | ||||
| 		} | ||||
| 		// Absolute symlinks reset any work we've already done. | ||||
| 		if filepath.IsAbs(dest) { | ||||
| 			path.Reset() | ||||
| 		} | ||||
| 		unsafePath = dest + string(filepath.Separator) + unsafePath | ||||
| 	} | ||||
|  | ||||
| 	// We have to clean path.String() here because it may contain '..' | ||||
| 	// components that are entirely lexical, but would be misleading otherwise. | ||||
| 	// And finally do a final clean to ensure that root is also lexically | ||||
| 	// clean. | ||||
| 	fullP := filepath.Clean(string(filepath.Separator) + path.String()) | ||||
| 	return filepath.Clean(root + fullP), nil | ||||
| } | ||||
|  | ||||
| // SecureJoin is a wrapper around SecureJoinVFS that just uses the os.* library | ||||
| // of functions as the VFS. If in doubt, use this function over SecureJoinVFS. | ||||
| func SecureJoin(root, unsafePath string) (string, error) { | ||||
| 	return SecureJoinVFS(root, unsafePath, nil) | ||||
| } | ||||
							
								
								
									
										41
									
								
								vendor/github.com/cyphar/filepath-securejoin/vfs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/cyphar/filepath-securejoin/vfs.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| // Copyright (C) 2017 SUSE LLC. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package securejoin | ||||
|  | ||||
| import "os" | ||||
|  | ||||
| // In future this should be moved into a separate package, because now there | ||||
| // are several projects (umoci and go-mtree) that are using this sort of | ||||
| // interface. | ||||
|  | ||||
| // VFS is the minimal interface necessary to use SecureJoinVFS. A nil VFS is | ||||
| // equivalent to using the standard os.* family of functions. This is mainly | ||||
| // used for the purposes of mock testing, but also can be used to otherwise use | ||||
| // SecureJoin with VFS-like system. | ||||
| type VFS interface { | ||||
| 	// Lstat returns a FileInfo describing the named file. If the file is a | ||||
| 	// symbolic link, the returned FileInfo describes the symbolic link. Lstat | ||||
| 	// makes no attempt to follow the link. These semantics are identical to | ||||
| 	// os.Lstat. | ||||
| 	Lstat(name string) (os.FileInfo, error) | ||||
|  | ||||
| 	// Readlink returns the destination of the named symbolic link. These | ||||
| 	// semantics are identical to os.Readlink. | ||||
| 	Readlink(name string) (string, error) | ||||
| } | ||||
|  | ||||
| // osVFS is the "nil" VFS, in that it just passes everything through to the os | ||||
| // module. | ||||
| type osVFS struct{} | ||||
|  | ||||
| // Lstat returns a FileInfo describing the named file. If the file is a | ||||
| // symbolic link, the returned FileInfo describes the symbolic link. Lstat | ||||
| // makes no attempt to follow the link. These semantics are identical to | ||||
| // os.Lstat. | ||||
| func (o osVFS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } | ||||
|  | ||||
| // Readlink returns the destination of the named symbolic link. These | ||||
| // semantics are identical to os.Readlink. | ||||
| func (o osVFS) Readlink(name string) (string, error) { return os.Readlink(name) } | ||||
							
								
								
									
										5
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| # github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8 | ||||
| # github.com/AdaLogics/go-fuzz-headers v0.0.0-20220706123152-fef3fe1bab07 | ||||
| ## explicit; go 1.13 | ||||
| github.com/AdaLogics/go-fuzz-headers | ||||
| # github.com/Microsoft/go-winio v0.5.2 | ||||
| @@ -166,6 +166,9 @@ github.com/coreos/go-systemd/v22/dbus | ||||
| # github.com/cpuguy83/go-md2man/v2 v2.0.1 | ||||
| ## explicit; go 1.11 | ||||
| github.com/cpuguy83/go-md2man/v2/md2man | ||||
| # github.com/cyphar/filepath-securejoin v0.2.3 | ||||
| ## explicit; go 1.13 | ||||
| github.com/cyphar/filepath-securejoin | ||||
| # github.com/davecgh/go-spew v1.1.1 | ||||
| ## explicit | ||||
| github.com/davecgh/go-spew/spew | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kazuyoshi Kato
					Kazuyoshi Kato