@@ -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