diff --git a/common/bytes.go b/common/bytes.go index bb40ac1d70..457aea96bf 100644 --- a/common/bytes.go +++ b/common/bytes.go @@ -17,9 +17,7 @@ // Package common contains various helper functions. package common -import ( - "encoding/hex" -) +import "encoding/hex" func ToHex(b []byte) string { hex := Bytes2Hex(b) @@ -57,12 +55,28 @@ func CopyBytes(b []byte) (copiedBytes []byte) { func HasHexPrefix(str string) bool { l := len(str) - return l >= 2 && str[0:2] == "0x" + return l >= 2 && (str[0:2] == "0x" || str[0:2] == "0X") +} + +func isHexCharacter(c byte) bool { + return ('0' <= c && c <= '9') || + ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F') } func IsHex(str string) bool { - l := len(str) - return l >= 4 && l%2 == 0 && str[0:2] == "0x" + if HasHexPrefix(str) { + str = str[2:] + } + if len(str)%2 != 0 { + return false + } + for _, c := range []byte(src) { + if !isHexCharacter(c) { + return false + } + } + return true } func Bytes2Hex(d []byte) string { diff --git a/common/bytes_test.go b/common/bytes_test.go index 71631e6dd7..081e039dd6 100644 --- a/common/bytes_test.go +++ b/common/bytes_test.go @@ -36,7 +36,7 @@ func (s *BytesSuite) TestCopyBytes(c *checker.C) { func (s *BytesSuite) TestIsHex(c *checker.C) { data1 := "a9e67e" - exp1 := false + exp1 := true res1 := IsHex(data1) c.Assert(res1, checker.DeepEquals, exp1) @@ -45,6 +45,15 @@ func (s *BytesSuite) TestIsHex(c *checker.C) { res2 := IsHex(data2) c.Assert(res2, checker.DeepEquals, exp2) + data3 := "0xa9e67e001" + exp3 := false + res3 := IsHex(data3) + c.Assert(res3, checker.DeepEquals, exp3) + + data4 := "0xHELLO_MY_NAME_IS_STEVEN_@#$^&*" + exp4 := false + res4 := IsHex(data4) + c.Assert(res4, checker.DeepEquals, exp4) } func (s *BytesSuite) TestLeftPadBytes(c *checker.C) { diff --git a/common/types.go b/common/types.go index d31bbf741b..670f0cf2f3 100644 --- a/common/types.go +++ b/common/types.go @@ -150,13 +150,10 @@ func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } // IsHexAddress verifies whether a string can represent a valid hex-encoded // Ethereum address or not. func IsHexAddress(s string) bool { - if len(s) == 2+2*AddressLength && IsHex(s) { - return true + if HasHexPrefix(s) { + return len(s) == 2+2*AddressLength && IsHex(s[2:]) } - if len(s) == 2*AddressLength && IsHex("0x"+s) { - return true - } - return false + return len(s) == 2*AddressLength && IsHex(s) } // Get the string representation of the underlying address diff --git a/common/types_test.go b/common/types_test.go index 6f3b315761..db636812ce 100644 --- a/common/types_test.go +++ b/common/types_test.go @@ -35,6 +35,30 @@ func TestBytesConversion(t *testing.T) { } } +func TestIsHexAddress(t *testing.T) { + tests := []struct { + str string + exp bool + }{ + {"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", true}, + {"5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", true}, + {"0X5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", true}, + {"0XAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", true}, + {"0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", true}, + {"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed1", false}, + {"0x5aaeb6053f3e94c9b9a09f33669435e7ef1beae", false}, + {"5aaeb6053f3e94c9b9a09f33669435e7ef1beaed11", false}, + {"0xxaaeb6053f3e94c9b9a09f33669435e7ef1beaed", false}, + } + + for _, test := range tests { + if result := IsHexAddress(test.str); result != test.exp { + t.Errorf("IsHexAddress(%s) == %v; expected %v", + test.str, result, test.exp) + } + } +} + func TestHashJsonValidation(t *testing.T) { var tests = []struct { Prefix string