Skip to content

Commit 79e3129

Browse files
committed
accounts/abi: validate fieldnames, fixes ethereum#24930 (ethereum#24932)
1 parent 9fb7846 commit 79e3129

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

accounts/abi/bind/base_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,3 +476,11 @@ func TestCall(t *testing.T) {
476476
}
477477
}
478478
}
479+
480+
// TestCrashers contains some strings which previously caused the abi codec to crash.
481+
func TestCrashers(t *testing.T) {
482+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`))
483+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"&"}]}]}]`))
484+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"----"}]}]}]`))
485+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"foo.Bar"}]}]}]`))
486+
}

accounts/abi/type.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"regexp"
2424
"strconv"
2525
"strings"
26+
"unicode"
27+
"unicode/utf8"
2628

2729
"github.com/XinFinOrg/XDPoSChain/common"
2830
)
@@ -172,6 +174,9 @@ func NewType(t string, internalType string, components []ArgumentMarshaling) (ty
172174
if err != nil {
173175
return Type{}, err
174176
}
177+
if !isValidFieldName(fieldName) {
178+
return Type{}, fmt.Errorf("field %d has invalid name", idx)
179+
}
175180
overloadedNames[fieldName] = fieldName
176181
fields = append(fields, reflect.StructField{
177182
Name: fieldName, // reflect.StructOf will panic for any exported field.
@@ -398,3 +403,30 @@ func getTypeSize(t Type) int {
398403
}
399404
return 32
400405
}
406+
407+
// isLetter reports whether a given 'rune' is classified as a Letter.
408+
// This method is copied from reflect/type.go
409+
func isLetter(ch rune) bool {
410+
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
411+
}
412+
413+
// isValidFieldName checks if a string is a valid (struct) field name or not.
414+
//
415+
// According to the language spec, a field name should be an identifier.
416+
//
417+
// identifier = letter { letter | unicode_digit } .
418+
// letter = unicode_letter | "_" .
419+
// This method is copied from reflect/type.go
420+
func isValidFieldName(fieldName string) bool {
421+
for i, c := range fieldName {
422+
if i == 0 && !isLetter(c) {
423+
return false
424+
}
425+
426+
if !(isLetter(c) || unicode.IsDigit(c)) {
427+
return false
428+
}
429+
}
430+
431+
return len(fieldName) > 0
432+
}

0 commit comments

Comments
 (0)