-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlibfuzzer.go
More file actions
86 lines (69 loc) · 2.05 KB
/
libfuzzer.go
File metadata and controls
86 lines (69 loc) · 2.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//go:build libfuzzer
// +build libfuzzer
package main
import (
"context"
"fmt"
"unsafe"
mutator "github.com/yandex-cloud/go-protobuf-mutator"
)
// #include <stdint.h>
import "C"
//export LLVMFuzzerTestOneInput
func LLVMFuzzerTestOneInput(data *C.char, size C.size_t) C.int {
ctx := context.Background()
// convert to golang structure with underlaying storage on C structure
gdata := unsafe.Slice((*byte)(unsafe.Pointer(data)), size)
// Load proto message
method, handler, message, err := ParseProtoMessage(gdata)
if err != nil {
fmt.Printf("Failed to parse proto message: %+v", err)
return 0
}
if message == nil {
fmt.Printf("Got empty message: method %s", string(method))
return 0
}
if err := handler.fuzz(ctx, string(method), message); err != nil {
// put your logic here to validate invalid response from server
fmt.Printf("API result from fuzzer: %+v", err)
panic("API error")
}
return 0
}
//export LLVMFuzzerInitialize
func LLVMFuzzerInitialize(argc *C.int, argv ***C.char) C.int {
ctx := context.Background()
go DumpCoverage(ctx)
// add init
return 0
}
//export LLVMFuzzerCustomMutator
func LLVMFuzzerCustomMutator(data *C.char, size C.size_t, maxSize C.size_t, seed C.uint) C.size_t {
// convert to golang structure with underlaying storage on C structure
gdata := unsafe.Slice((*byte)(unsafe.Pointer(data)), size)
// Load proto message
method, _, message, err := ParseProtoMessage(gdata)
if err != nil {
fmt.Printf("Failed to parse proto message: %+v", err)
return 0
}
if message == nil {
method := []byte("ExampleService/Get\n")
copy(gdata, method)
return C.size_t(len(method))
}
mutator := mutator.New(int64(seed), int(maxSize-size))
if err := mutator.MutateProto(message); err != nil {
fmt.Printf("Failed to mutate message: %+v", err)
return 0
}
gdata = unsafe.Slice((*byte)(unsafe.Pointer(data)), maxSize)
// copy result back to C storage
newSize, err := StoreMessage(gdata, method, message)
if err != nil {
fmt.Printf("Failed to store new message: %+v", err)
return 0
}
return C.size_t(newSize)
}