Last active
December 8, 2022 17:45
-
-
Save rc-mattschwager/e802fcaec17ff17b281c1f0e5d7cec28 to your computer and use it in GitHub Desktop.
Code for "Fuzzing Golang msgpack for fun and panic" blog post
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module msgpackfuzz | |
go 1.17 | |
require ( | |
github.com/dvyukov/go-fuzz v0.0.0-20220726122315-1d375ef9f9f6 // indirect | |
github.com/dvyukov/go-fuzz-corpus v0.0.0-20190920191254-c42c1b2914c7 // indirect | |
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect | |
github.com/shamaton/msgpack/v2 v2.1.0 // indirect | |
github.com/stephens2424/writerset v1.0.2 // indirect | |
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect | |
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 // indirect | |
golang.org/x/tools v0.1.12 // indirect | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"flag" | |
"fmt" | |
"os" | |
"path/filepath" | |
"reflect" | |
"github.com/shamaton/msgpack/v2" | |
) | |
type Primitive struct { | |
Nil *int | |
Bool bool | |
Int int | |
Uint uint | |
Float32 float32 | |
Float64 float64 | |
String string | |
Bytes []byte | |
} | |
type Struct struct { | |
Int int | |
String string | |
} | |
type Container struct { | |
Array []int | |
Map map[string]int | |
Nested Struct | |
} | |
func generateCorpus(directory string) { | |
primitives := []Primitive{ | |
Primitive{Nil: nil, Bool: true, Int: -100, Uint: 0, Float32: 3.1415, Float64: -3.1415, String: "foo", Bytes: []byte("bar")}, | |
Primitive{Nil: nil, Bool: false, Int: 0, Uint: 100, Float32: 3.1415, Float64: -3.1415, String: "", Bytes: []byte("")}, | |
Primitive{Nil: nil, Bool: false, Int: 1000, Uint: 1000, Float32: 3.1415, Float64: -3.1415, String: "\n", Bytes: []byte("\n")}, | |
} | |
containers := []Container{ | |
Container{Array: []int{1, 2, 3, 4, 5}, Map: map[string]int{"1": 1, "2": 2, "3": 3}, Nested: Struct{Int: 42, String: "bar"}}, | |
Container{Array: []int{}, Map: map[string]int{}, Nested: Struct{Int: 0, String: ""}}, | |
} | |
for i, primitive := range primitives { | |
data, err := msgpack.Marshal(primitive) | |
if err != nil { | |
panic(err) | |
} | |
r := Primitive{} | |
err = msgpack.Unmarshal(data, &r) | |
if err != nil { | |
panic(err) | |
} | |
if !reflect.DeepEqual(r, primitive) { | |
panic("r != primitive") | |
} | |
filename := filepath.Join(directory, fmt.Sprintf("primitive-%d.mp", i)) | |
err = os.WriteFile(filename, data, 0644) | |
if err != nil { | |
panic(err) | |
} | |
} | |
for i, container := range containers { | |
data, err := msgpack.Marshal(container) | |
if err != nil { | |
panic(err) | |
} | |
r := Container{} | |
err = msgpack.Unmarshal(data, &r) | |
if err != nil { | |
panic(err) | |
} | |
if !reflect.DeepEqual(r, container) { | |
panic("r != container") | |
} | |
filename := filepath.Join(directory, fmt.Sprintf("container-%d.mp", i)) | |
err = os.WriteFile(filename, data, 0644) | |
if err != nil { | |
panic(err) | |
} | |
} | |
} | |
func Fuzz(data []byte) int { | |
var r interface{} | |
err := msgpack.Unmarshal(data, &r) | |
if err != nil { | |
return 0 | |
} | |
return 1 | |
} | |
func main() { | |
var generate = flag.Bool("generate", false, "Generate corpus directory") | |
var filename = flag.String("filename", "", "Unmarshal filename") | |
flag.Parse() | |
if *generate { | |
corpusDir := "corpus" | |
err := os.MkdirAll(corpusDir, 0755) | |
if err != nil { | |
panic(err) | |
} | |
generateCorpus(corpusDir) | |
return | |
} | |
if *filename == "" { | |
fmt.Println("Specify a msgpack file with '-filename' to unmarshal") | |
return | |
} | |
data, err := os.ReadFile(*filename) | |
if err != nil { | |
panic(err) | |
} | |
var r interface{} | |
err = msgpack.Unmarshal(data, &r) | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println(r) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment