From aa46894dd5b15bce5a726b57936d9ca4c584cb79 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 17 May 2019 11:45:22 +0200 Subject: [PATCH] core/signer: add fuzzer testcases + crashfixes --- signer/core/signed_data.go | 31 +++++++-- signer/core/signed_data_test.go | 34 ++++++++++ .../2850f6ccf2d7f5f846dfb73119b60e09e712783f | 38 +++++++++++ .../36fb987a774011dc675e1b5246ac5c1d44d84d92 | 60 +++++++++++++++++ .../37ec7b55c7ba014cced204c5f9989d2d0eb9ff6d | 38 +++++++++++ .../582fa92154b784daa1faa293b695fa388fe34bf1 | 1 + .../ab57cb2b2b5ce614efe13a47bc73814580f2cce8 | 54 ++++++++++++++++ .../e4303e23ca34fbbc43164a232b2caa7a3af2bf8d | 64 +++++++++++++++++++ .../f658340af009dd4a35abe645a00a7b732bc30921 | 1 + 9 files changed, 314 insertions(+), 7 deletions(-) create mode 100644 signer/core/testdata/fuzzing/2850f6ccf2d7f5f846dfb73119b60e09e712783f create mode 100644 signer/core/testdata/fuzzing/36fb987a774011dc675e1b5246ac5c1d44d84d92 create mode 100644 signer/core/testdata/fuzzing/37ec7b55c7ba014cced204c5f9989d2d0eb9ff6d create mode 100644 signer/core/testdata/fuzzing/582fa92154b784daa1faa293b695fa388fe34bf1 create mode 100644 signer/core/testdata/fuzzing/ab57cb2b2b5ce614efe13a47bc73814580f2cce8 create mode 100644 signer/core/testdata/fuzzing/e4303e23ca34fbbc43164a232b2caa7a3af2bf8d create mode 100644 signer/core/testdata/fuzzing/f658340af009dd4a35abe645a00a7b732bc30921 diff --git a/signer/core/signed_data.go b/signer/core/signed_data.go index fb81955dd6..9b0753e8b3 100644 --- a/signer/core/signed_data.go +++ b/signer/core/signed_data.go @@ -96,6 +96,9 @@ func (t *Type) typeName() string { } func (t *Type) isReferenceType() bool { + if len(t.Type) == 0 { + return false + } // Reference types must have a leading uppercase characer return unicode.IsUpper([]rune(t.Type)[0]) } @@ -378,9 +381,11 @@ func (typedData *TypedData) Dependencies(primaryType string, found []string) []s func (typedData *TypedData) EncodeType(primaryType string) hexutil.Bytes { // Get dependencies primary first, then alphabetical deps := typedData.Dependencies(primaryType, []string{}) - slicedDeps := deps[1:] - sort.Strings(slicedDeps) - deps = append([]string{primaryType}, slicedDeps...) + if len(deps) > 0 { + slicedDeps := deps[1:] + sort.Strings(slicedDeps) + deps = append([]string{primaryType}, slicedDeps...) + } // Format as a string with fields var buffer bytes.Buffer @@ -728,9 +733,12 @@ func (typedData *TypedData) formatData(primaryType string, data map[string]inter } } } else if typedData.Types[field.Type] != nil { - mapValue, _ := encValue.(map[string]interface{}) - mapOutput := typedData.formatData(field.Type, mapValue) - item.Value = mapOutput + if mapValue, ok := encValue.(map[string]interface{}); ok { + mapOutput := typedData.formatData(field.Type, mapValue) + item.Value = mapOutput + } else { + item.Value = "" + } } else { primitiveOutput := formatPrimitiveValue(field.Type, encValue) item.Value = primitiveOutput @@ -791,7 +799,16 @@ func (nvt *NameValueType) Pprint(depth int) string { // Validate checks if the types object is conformant to the specs func (t Types) validate() error { for typeKey, typeArr := range t { - for _, typeObj := range typeArr { + if len(typeKey) == 0 { + return fmt.Errorf("empty type key") + } + for i, typeObj := range typeArr { + if len(typeObj.Type) == 0 { + return fmt.Errorf("type %v:%d: empty Type", typeKey, i) + } + if len(typeObj.Name) == 0 { + return fmt.Errorf("type %v:%d: empty Name", typeKey, i) + } if typeKey == typeObj.Type { return fmt.Errorf("type '%s' cannot reference itself", typeObj.Type) } diff --git a/signer/core/signed_data_test.go b/signer/core/signed_data_test.go index bf5298b2b0..6f0e53e12d 100644 --- a/signer/core/signed_data_test.go +++ b/signer/core/signed_data_test.go @@ -373,3 +373,37 @@ func TestJsonFiles(t *testing.T) { } } } + +// TestFuzzerFiles tests some files that have been found by fuzzing to cause +// crashes or hangs. +func TestFuzzerFiles(t *testing.T) { + corpusdir := path.Join("testdata", "fuzzing") + testfiles, err := ioutil.ReadDir(corpusdir) + if err != nil { + t.Fatalf("failed reading files: %v", err) + } + verbose := false + for i, fInfo := range testfiles { + data, err := ioutil.ReadFile(path.Join(corpusdir, fInfo.Name())) + if err != nil { + t.Errorf("Failed to read file %v: %v", fInfo.Name(), err) + continue + } + var typedData core.TypedData + err = json.Unmarshal([]byte(data), &typedData) + if err != nil { + t.Errorf("Test %d, file %v, json unmarshalling failed: %v", i, fInfo.Name(), err) + continue + } + _, err = typedData.EncodeData("EIP712Domain", typedData.Domain.Map(), 1) + if verbose && err != nil { + fmt.Printf("%d, EncodeData[1] err: %v\n", i, err) + } + _, err = typedData.EncodeData(typedData.PrimaryType, typedData.Message, 1) + if verbose && err != nil { + fmt.Printf("%d, EncodeData[2] err: %v\n", i, err) + } + typedData.PrettyPrint() + typedData.Format() + } +} diff --git a/signer/core/testdata/fuzzing/2850f6ccf2d7f5f846dfb73119b60e09e712783f b/signer/core/testdata/fuzzing/2850f6ccf2d7f5f846dfb73119b60e09e712783f new file mode 100644 index 0000000000..8229a333ca --- /dev/null +++ b/signer/core/testdata/fuzzing/2850f6ccf2d7f5f846dfb73119b60e09e712783f @@ -0,0 +1,38 @@ +{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Mail": [ + { + "name": "test", + "type": "uint8" + } + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": "1", + "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "test":"255.3" + } +} diff --git a/signer/core/testdata/fuzzing/36fb987a774011dc675e1b5246ac5c1d44d84d92 b/signer/core/testdata/fuzzing/36fb987a774011dc675e1b5246ac5c1d44d84d92 new file mode 100644 index 0000000000..fea82b42c6 --- /dev/null +++ b/signer/core/testdata/fuzzing/36fb987a774011dc675e1b5246ac5c1d44d84d92 @@ -0,0 +1,60 @@ +{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Foo": [ + { + "name": "addys", + "type": "address[]" + }, + { + "name": "stringies", + "type": "string[]" + }, + { + "name": "inties", + "type": "uint[]" + } + ] + }, + "primaryType": "Foo", + "domain": { + "name": "Lorem", + "version": "1", + "chainId": "1", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "addys": [ + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000003" + ], + "stringies": [ + "lorem", + "ipsum", + "dolores" + ], + "inties": [ + "0x0000000000000000000000000000000000000001", + "3", + 4.0 + ] + } +} diff --git a/signer/core/testdata/fuzzing/37ec7b55c7ba014cced204c5f9989d2d0eb9ff6d b/signer/core/testdata/fuzzing/37ec7b55c7ba014cced204c5f9989d2d0eb9ff6d new file mode 100644 index 0000000000..c63ed41f9c --- /dev/null +++ b/signer/core/testdata/fuzzing/37ec7b55c7ba014cced204c5f9989d2d0eb9ff6d @@ -0,0 +1,38 @@ +{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Mail": [ + { + "name": "test", + "type": "uint8" + } + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": "1", + "verifyingContract": "0xCCCcccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "test":257 + } +} diff --git a/signer/core/testdata/fuzzing/582fa92154b784daa1faa293b695fa388fe34bf1 b/signer/core/testdata/fuzzing/582fa92154b784daa1faa293b695fa388fe34bf1 new file mode 100644 index 0000000000..9bc43938d5 --- /dev/null +++ b/signer/core/testdata/fuzzing/582fa92154b784daa1faa293b695fa388fe34bf1 @@ -0,0 +1 @@ +{"domain":{"version":"0","chainId":""}} \ No newline at end of file diff --git a/signer/core/testdata/fuzzing/ab57cb2b2b5ce614efe13a47bc73814580f2cce8 b/signer/core/testdata/fuzzing/ab57cb2b2b5ce614efe13a47bc73814580f2cce8 new file mode 100644 index 0000000000..fe27de916c --- /dev/null +++ b/signer/core/testdata/fuzzing/ab57cb2b2b5ce614efe13a47bc73814580f2cce8 @@ -0,0 +1,54 @@ +{ "types": { "":[ { + "name": "name", + "type":"string" }, + { + "name":"version", + "type": "string" }, { + "name": "chaiI", + "type":"uint256 . ad nowretig omeedifere" }, { + "ae": "eifinC", + "ty":"dess" + } + ], + "Person":[ + { + "name":"name", + "type": "string" + }, { + "name":"tes", "type":"it8" + }, + { "name":"t", "tye":"uit8" + }, + { + "a":"ale", + "type": "ress" + } + ], + "Mail": [ + { + "name":"from", "type":"Person" }, + { + "name": "to", "type": "Person" + }, + { + "name": "contents", + "type": "string" + } + ] + }, "primaryType": "Mail", + "domain": { +"name":"theMail", "version": "1", + "chainId": "1", + "verifyingntract": "0xCcccCCCcCCCCCCCcCCcCCCcCcccccC" + }, + "message": { "from": { + "name": "Cow", + "test": "3", + "est2":5.0, + "llt": "0xcD2a3938E13D947E0bE734DfDD86" }, "to": { "name": "Bob", + "ts":"", + "tet2": 5, + "allet": "0bBBBBbbBBbbbbBbbBbbbbBBBbB" + }, + "contents": "Hello, Bob!" } +} \ No newline at end of file diff --git a/signer/core/testdata/fuzzing/e4303e23ca34fbbc43164a232b2caa7a3af2bf8d b/signer/core/testdata/fuzzing/e4303e23ca34fbbc43164a232b2caa7a3af2bf8d new file mode 100644 index 0000000000..c5e14b39ed --- /dev/null +++ b/signer/core/testdata/fuzzing/e4303e23ca34fbbc43164a232b2caa7a3af2bf8d @@ -0,0 +1,64 @@ +{ + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "int" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "Person": [ + { + "name": "name", + "type": "string" + }, + { + "name": "wallet", + "type": "address" + } + ], + "Mail": [ + { + "name": "from", + "type": "Person" + }, + { + "name": "to", + "type": "Mail" + }, + { + "name": "s", + "type": "Person" + } + ] + }, + "primaryType": "Mail", + "domain": { + "name": "l", + "version": "1", + "chainId": "", + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC" + }, + "message": { + "from": { + "name": "", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "": "" + } +} diff --git a/signer/core/testdata/fuzzing/f658340af009dd4a35abe645a00a7b732bc30921 b/signer/core/testdata/fuzzing/f658340af009dd4a35abe645a00a7b732bc30921 new file mode 100644 index 0000000000..c4841cb07b --- /dev/null +++ b/signer/core/testdata/fuzzing/f658340af009dd4a35abe645a00a7b732bc30921 @@ -0,0 +1 @@ +{"types":{"0":[{}]}} \ No newline at end of file