From d22574a627d6b4d6964cb0c2be52f2831ea14945 Mon Sep 17 00:00:00 2001 From: louisehong Date: Mon, 7 Sep 2020 19:00:32 +0800 Subject: [PATCH] Optimized ip checking algorithm for ipv6 IPv6 parser should fail with 8 groups plus one blank --- internal/tools/ipparser.go | 70 ++++++++++++++++++++++++++++------ internal/tools/iptools_test.go | 43 +++++++++++++++++++++ 2 files changed, 101 insertions(+), 12 deletions(-) diff --git a/internal/tools/ipparser.go b/internal/tools/ipparser.go index 602ffd2..b39c473 100644 --- a/internal/tools/ipparser.go +++ b/internal/tools/ipparser.go @@ -46,7 +46,7 @@ func ValidIP4(IP string) bool { return true } -func ValidIP6(str string) bool { +func ValidIP6Re(str string) bool { str = strings.Trim(str, " ") return ipv6re0.MatchString(str) @@ -67,24 +67,70 @@ func GetIP6FromString(str string) []string { //1. 用“:”分割字符串,若长度不等于8,则return Neither //2. 遍历每一个数组的每一个元素,若元素的长度大于4,则return Neither //3. 判断每一个元素的字符,若出现非0-9,A-F的字符,则return Neither -func isIPV6(IP string) bool { +func ValidIP6(IP string) bool { IP = strings.ToUpper(IP) - arr := strings.Split(IP, ":") - if len(arr) != 8 { + n := len(IP) + if n > 39 || n == 0 { return false } - for _, elem := range arr { - if elem == "" || len(elem) > 4 { - return false - } - for _, c := range elem { - if (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') { + // 以 ":" 结尾 但是只有一个 + if strings.HasSuffix(IP, ":") && !strings.HasSuffix(IP, "::") { + return false + } + // 如果"::" 有两个以上 + if strings.Count(IP, "::") > 1 { + return false + } + // 如果 ":" 有8个以上 + if strings.Count(IP, ":") > 8 { + return false + } + tmp := strings.Split(IP, ":") + // 如果有ipv4, 则返回真, 前面的部分未校验。 + if ValidIP4(tmp[len(tmp)-1]) { + return true + } + if strings.Contains(IP,"::") { + var count int + for _, v := range tmp { + if v != "" { + count++ continue - } else { - return false } } + if count == 8 { + return false + } } + + // 对每个元素进行遍历 + for k := 0; k < n-1; { + if IP[k] == ':' { + k++ + continue + } else if valid(IP[k]) { + var bits int + for valid(IP[k]) { + k++ + bits++ + if bits > 4 { + return false + } + if k == n { + break + } + } + + } else { + return false + } + } + + // 到了这一步, 可以确定是ipv6 return true } + +func valid(i uint8) bool { + return (i >= 'A' && i <= 'F') || (i >= '0' && i <= '9') +} \ No newline at end of file diff --git a/internal/tools/iptools_test.go b/internal/tools/iptools_test.go index d6fc8af..04a2961 100644 --- a/internal/tools/iptools_test.go +++ b/internal/tools/iptools_test.go @@ -42,6 +42,7 @@ func TestValidIP6(t *testing.T) { "::4:5:6:7:8", "::3:4:5:6:7:8", "::2:3:4:5:6:7:8", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "::192.168.1.1", "::ffff:135.75.43.52", @@ -52,6 +53,8 @@ func TestValidIP6(t *testing.T) { "A:0f:0F:FFFF1:5:6:7:8", "G:0f:0F:FFFF:5:6:7:8", "2001::25de::cade", + "2001:0db8:85a3:0:0:8A2E:0370:73341", + "a1:a2:a3:a4::b1:b2:b3:b4", } for _, i := range ipv6Valid { @@ -66,3 +69,43 @@ func TestValidIP6(t *testing.T) { } } } + +func BenchmarkValidIP6Re(b *testing.B) { + b.ResetTimer() + origin := "::ffff:135.75.43.52" + for i:=0; i