diff --git a/examples/nft-nd-nns/nns.go b/examples/nft-nd-nns/nns.go index 5f67f1fba..fb21e1c1d 100644 --- a/examples/nft-nd-nns/nns.go +++ b/examples/nft-nd-nns/nns.go @@ -581,23 +581,47 @@ func checkIPv6(data string) bool { if l < 3 || 8 < l { return false } - if fragments[0] == "2001" { // example addresses prefix + var hasEmpty bool + nums := make([]int, 8) + for i, f := range fragments { + if len(f) == 0 { + if i == 0 { + nums[i] = 0 + } else if i == l-1 { + nums[7] = 0 + } else if hasEmpty { + return false + } else { + hasEmpty = true + endIndex := 9 - l + i + for j := i; j < endIndex; j++ { + nums[j] = 0 + } + } + } else { + if len(f) > 4 { + return false + } + n := std.Atoi(f, 16) + if 65535 < n { + panic("fragment overflows uint16: " + f) + } + idx := i + if hasEmpty { + idx = i + 8 - l + } + nums[idx] = n + } + } + + f0 := nums[0] + if f0 < 0x2000 || f0 == 0x2002 || f0 == 0x3ffe || f0 > 0x3fff { // IPv6 Global Unicast https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml return false } - var hasEmpty bool - for i := 1; i < l; i++ { - f := fragments[i] - fLen := len(f) - if fLen == 0 { - if i < l-1 && hasEmpty { - return false - } - hasEmpty = true - } else { - if fLen > 4 { - return false - } - _ = std.Atoi(f, 16) // check it won't panic + if f0 == 0x2001 { + f1 := nums[1] + if f1 < 0x200 || f1 == 0xdb8 { + return false } } return true diff --git a/pkg/core/nonnative_name_service_test.go b/pkg/core/nonnative_name_service_test.go index c7b4f1428..43486b2fb 100644 --- a/pkg/core/nonnative_name_service_test.go +++ b/pkg/core/nonnative_name_service_test.go @@ -197,7 +197,7 @@ func TestSetGetRecord(t *testing.T) { testNameServiceInvoke(t, bc, nsHash, "getRecord", "1.2.3.4", "neo.com", int64(nns.A)) testNameServiceInvoke(t, bc, nsHash, "setRecord", stackitem.Null{}, "neo.com", int64(nns.A), "1.2.3.4") testNameServiceInvoke(t, bc, nsHash, "getRecord", "1.2.3.4", "neo.com", int64(nns.A)) - testNameServiceInvoke(t, bc, nsHash, "setRecord", stackitem.Null{}, "neo.com", int64(nns.AAAA), "2002:0000:1f1f:0000:0000:0100:11a0:addf") + testNameServiceInvoke(t, bc, nsHash, "setRecord", stackitem.Null{}, "neo.com", int64(nns.AAAA), "2001:0201:1f1f:0000:0000:0100:11a0:11df") testNameServiceInvoke(t, bc, nsHash, "setRecord", stackitem.Null{}, "neo.com", int64(nns.CNAME), "nspcc.ru") testNameServiceInvoke(t, bc, nsHash, "setRecord", stackitem.Null{}, "neo.com", int64(nns.TXT), "sometext") @@ -238,30 +238,32 @@ func TestSetGetRecord(t *testing.T) { {Type: nns.A, Name: "1.1", ShouldFail: true}, {Type: nns.A, Name: "257", ShouldFail: true}, {Type: nns.A, Name: "1", ShouldFail: true}, - {Type: nns.AAAA, Name: "2001:db8::8:800:200c:417a", ShouldFail: true}, - {Type: nns.AAAA, Name: "ff01:db8::8:800:200c:417a"}, - {Type: nns.AAAA, Name: "ff01::101"}, - {Type: nns.AAAA, Name: "::1"}, - {Type: nns.AAAA, Name: "::"}, - {Type: nns.AAAA, Name: "2001:db8:0:0:8:800:200c:417a", ShouldFail: true}, - {Type: nns.AAAA, Name: "ff01:db8:0:0:8:800:200c:417a"}, - {Type: nns.AAAA, Name: "ff01:0:0:0:0:0:0:101"}, - {Type: nns.AAAA, Name: "2001:0:0:0:0:0:0:101", ShouldFail: true}, - {Type: nns.AAAA, Name: "ff01:0:0:0:0:0:0:101"}, - {Type: nns.AAAA, Name: "0:0:0:0:0:0:0:1"}, - {Type: nns.AAAA, Name: "2001:0:0:0:0:0:0:1", ShouldFail: true}, - {Type: nns.AAAA, Name: "0:0:0:0:0:0:0:0"}, - {Type: nns.AAAA, Name: "2001:0:0:0:0:0:0:0", ShouldFail: true}, - {Type: nns.AAAA, Name: "2001:DB8::8:800:200C:417A", ShouldFail: true}, - {Type: nns.AAAA, Name: "FF01:DB8::8:800:200C:417A"}, - {Type: nns.AAAA, Name: "FF01::101"}, - {Type: nns.AAAA, Name: "fF01::101"}, - {Type: nns.AAAA, Name: "2001:DB8:0:0:8:800:200C:417A", ShouldFail: true}, - {Type: nns.AAAA, Name: "FF01:DB8:0:0:8:800:200C:417A"}, - {Type: nns.AAAA, Name: "FF01:0:0:0:0:0:0:101"}, - {Type: nns.AAAA, Name: "::ffff:1.01.1.01", ShouldFail: true}, + // {2000} & {2001} & ]2002, 3ffe[ & {3fff} are valid values for IPv6 fragment0 + {Type: nns.AAAA, Name: "2002:db8::8:800:200c:417a", ShouldFail: true}, + {Type: nns.AAAA, Name: "3ffd:1b8::8:800:200c:417a"}, + {Type: nns.AAAA, Name: "3ffd::101"}, + {Type: nns.AAAA, Name: "2003::1"}, + {Type: nns.AAAA, Name: "2003::"}, + {Type: nns.AAAA, Name: "2002:db8:0:0:8:800:200c:417a", ShouldFail: true}, + {Type: nns.AAAA, Name: "3ffd:db8:0:0:8:800:200c:417a"}, + {Type: nns.AAAA, Name: "3ffd:0:0:0:0:0:0:101"}, + {Type: nns.AAAA, Name: "2002:0:0:0:0:0:0:101", ShouldFail: true}, + {Type: nns.AAAA, Name: "3ffd:0:0:0:0:0:0:101"}, + {Type: nns.AAAA, Name: "2001:200:0:0:0:0:0:1"}, + {Type: nns.AAAA, Name: "0:0:0:0:0:0:0:1", ShouldFail: true}, + {Type: nns.AAAA, Name: "2002:0:0:0:0:0:0:1", ShouldFail: true}, + {Type: nns.AAAA, Name: "2001:200:0:0:0:0:0:0"}, + {Type: nns.AAAA, Name: "2002:0:0:0:0:0:0:0", ShouldFail: true}, + {Type: nns.AAAA, Name: "2002:DB8::8:800:200C:417A", ShouldFail: true}, + {Type: nns.AAAA, Name: "3FFD:1B8::8:800:200C:417A"}, + {Type: nns.AAAA, Name: "3FFD::101"}, + {Type: nns.AAAA, Name: "3fFD::101"}, + {Type: nns.AAAA, Name: "2002:DB8:0:0:8:800:200C:417A", ShouldFail: true}, + {Type: nns.AAAA, Name: "3FFD:DB8:0:0:8:800:200C:417A"}, + {Type: nns.AAAA, Name: "3FFD:0:0:0:0:0:0:101"}, + {Type: nns.AAAA, Name: "3FFD::ffff:1.01.1.01", ShouldFail: true}, {Type: nns.AAAA, Name: "2001:DB8:0:0:8:800:200C:4Z", ShouldFail: true}, - {Type: nns.AAAA, Name: "::13.1.68.3", ShouldFail: true}, + {Type: nns.AAAA, Name: "2001::13.1.68.3", ShouldFail: true}, } for _, testCase := range testCases { var expected interface{}