Skip to content

Commit af02e97

Browse files
authored
accounts/abi: validate fieldnames, fixes #24930 (#24932)
1 parent 59ac229 commit af02e97

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
@@ -488,3 +488,11 @@ func TestCall(t *testing.T) {
488488
}
489489
}
490490
}
491+
492+
// TestCrashers contains some strings which previously caused the abi codec to crash.
493+
func TestCrashers(t *testing.T) {
494+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"_1"}]}]}]`))
495+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"&"}]}]}]`))
496+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"----"}]}]}]`))
497+
abi.JSON(strings.NewReader(`[{"inputs":[{"type":"tuple[]","components":[{"type":"bool","name":"foo.Bar"}]}]}]`))
498+
}

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

0 commit comments

Comments
 (0)