this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

pkg/net: return errors for unexpected types in IP validators

netGetIP and netGetIPCIDR silently accepted any value type,
returning zero values instead of errors. This caused net.IPCIDR
to incorrectly succeed on non-string types like integers,
and other validators like net.IP, net.IPv4, net.IPv6 to give
less informative "does not satisfy" errors without details.

Change netGetIP to return (netip.Addr, error) and netGetIPCIDR
to return an error for unexpected types. Update all callers:
IPv4, IPv6, IP, LoopbackIP, MulticastIP, InterfaceLocalMulticastIP,
LinkLocalMulticastIP, LinkLocalUnicastIP, GlobalUnicastIP,
UnspecifiedIP now return (bool, error). ToIP4, ToIP16, IPString,
AddIP, InCIDR, CompareIP, and JoinHostPort updated accordingly.

As a side effect, all error messages now include the underlying
cause from the standard library, e.g. "ParseAddr(...): IPv4 field
has value >255" rather than just "does not satisfy net.IPv4".

Fixes #3979.

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: Ica7468aaaf87d3e9c0ad94a616ebecdec6c49d9c
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1233776
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+134 -93
+4 -3
pkg/net/host.go
··· 55 55 hostStr := "" 56 56 switch host.Kind() { 57 57 case cue.ListKind: 58 - ipdata := netGetIP(host) 59 - if !ipdata.IsValid() { 58 + ipdata, ipErr := netGetIP(host) 59 + if ipErr != nil { 60 60 err = fmt.Errorf("invalid host %s", host) 61 + } else { 62 + hostStr = ipdata.String() 61 63 } 62 - hostStr = ipdata.String() 63 64 case cue.BytesKind: 64 65 var b []byte 65 66 b, err = host.Bytes()
+95 -57
pkg/net/ip.go
··· 30 30 IPv6len = 16 31 31 ) 32 32 33 - func netGetIP(ip cue.Value) (goip netip.Addr) { 33 + func netGetIP(ip cue.Value) (netip.Addr, error) { 34 34 switch ip.Kind() { 35 35 case cue.StringKind: 36 36 s, err := ip.String() 37 37 if err != nil { 38 - return netip.Addr{} 38 + return netip.Addr{}, err 39 39 } 40 40 goip, err := netip.ParseAddr(s) 41 41 if err != nil { 42 - return netip.Addr{} 42 + return netip.Addr{}, err 43 43 } 44 - return goip 44 + return goip, nil 45 45 46 46 case cue.BytesKind: 47 47 b, err := ip.Bytes() 48 48 if err != nil { 49 - return netip.Addr{} 49 + return netip.Addr{}, err 50 50 } 51 51 goip, err := netip.ParseAddr(string(b)) 52 52 if err != nil { 53 - return netip.Addr{} 53 + return netip.Addr{}, err 54 54 } 55 - return goip 55 + return goip, nil 56 56 57 57 case cue.ListKind: 58 58 iter, err := ip.List() 59 59 if err != nil { 60 - return netip.Addr{} 60 + return netip.Addr{}, err 61 61 } 62 62 var bytes []byte 63 63 for iter.Next() { 64 64 v, err := iter.Value().Int64() 65 65 if err != nil { 66 - return netip.Addr{} 66 + return netip.Addr{}, err 67 67 } 68 68 if v < 0 || 255 < v { 69 - return netip.Addr{} 69 + return netip.Addr{}, fmt.Errorf("invalid IP byte value %d", v) 70 70 } 71 71 bytes = append(bytes, byte(v)) 72 72 } 73 73 goip, ok := netip.AddrFromSlice(bytes) 74 74 if !ok { 75 - return netip.Addr{} 75 + return netip.Addr{}, fmt.Errorf("invalid IP length %d", len(bytes)) 76 76 } 77 - return goip 77 + return goip, nil 78 78 79 79 default: 80 - // TODO: return canonical invalid type. 81 - return netip.Addr{} 80 + return netip.Addr{}, fmt.Errorf("invalid type %v for IP address", ip.Kind()) 82 81 } 83 82 } 84 83 ··· 107 106 return &cidr, nil 108 107 109 108 default: 110 - // TODO: return canonical invalid type. 111 - return nil, nil 109 + return nil, fmt.Errorf("invalid type %v for IP CIDR", ip.Kind()) 112 110 } 113 111 } 114 112 ··· 136 134 // IPv4 reports whether ip is a valid IPv4 address. 137 135 // 138 136 // The address may be a string or list of bytes. 139 - func IPv4(ip cue.Value) bool { 137 + func IPv4(ip cue.Value) (bool, error) { 140 138 // TODO: convert to native CUE. 141 - return netGetIP(ip).Is4() 139 + goip, err := netGetIP(ip) 140 + if err != nil { 141 + return false, err 142 + } 143 + return goip.Is4(), nil 142 144 } 143 145 144 146 // IPv6 reports whether ip is a valid IPv6 address. 145 147 // 146 148 // The address may be a string or list of bytes. 147 - func IPv6(ip cue.Value) bool { 148 - return netGetIP(ip).Is6() 149 + func IPv6(ip cue.Value) (bool, error) { 150 + goip, err := netGetIP(ip) 151 + if err != nil { 152 + return false, err 153 + } 154 + return goip.Is6(), nil 149 155 } 150 156 151 157 // IP reports whether ip is a valid IPv4 or IPv6 address. 152 158 // 153 159 // The address may be a string or list of bytes. 154 - func IP(ip cue.Value) bool { 160 + func IP(ip cue.Value) (bool, error) { 155 161 // TODO: convert to native CUE. 156 - return netGetIP(ip).IsValid() 162 + goip, err := netGetIP(ip) 163 + if err != nil { 164 + return false, err 165 + } 166 + return goip.IsValid(), nil 157 167 } 158 168 159 169 // IPCIDR reports whether ip is a valid IPv4 or IPv6 address with CIDR subnet notation. ··· 165 175 } 166 176 167 177 // LoopbackIP reports whether ip is a loopback address. 168 - func LoopbackIP(ip cue.Value) bool { 169 - return netGetIP(ip).IsLoopback() 178 + func LoopbackIP(ip cue.Value) (bool, error) { 179 + goip, err := netGetIP(ip) 180 + if err != nil { 181 + return false, err 182 + } 183 + return goip.IsLoopback(), nil 170 184 } 171 185 172 186 // MulticastIP reports whether ip is a multicast address. 173 - func MulticastIP(ip cue.Value) bool { 174 - return netGetIP(ip).IsMulticast() 187 + func MulticastIP(ip cue.Value) (bool, error) { 188 + goip, err := netGetIP(ip) 189 + if err != nil { 190 + return false, err 191 + } 192 + return goip.IsMulticast(), nil 175 193 } 176 194 177 195 // InterfaceLocalMulticastIP reports whether ip is an interface-local multicast 178 196 // address. 179 - func InterfaceLocalMulticastIP(ip cue.Value) bool { 180 - return netGetIP(ip).IsInterfaceLocalMulticast() 197 + func InterfaceLocalMulticastIP(ip cue.Value) (bool, error) { 198 + goip, err := netGetIP(ip) 199 + if err != nil { 200 + return false, err 201 + } 202 + return goip.IsInterfaceLocalMulticast(), nil 181 203 } 182 204 183 205 // LinkLocalMulticastIP reports whether ip is a link-local multicast address. 184 - func LinkLocalMulticastIP(ip cue.Value) bool { 185 - return netGetIP(ip).IsLinkLocalMulticast() 206 + func LinkLocalMulticastIP(ip cue.Value) (bool, error) { 207 + goip, err := netGetIP(ip) 208 + if err != nil { 209 + return false, err 210 + } 211 + return goip.IsLinkLocalMulticast(), nil 186 212 } 187 213 188 214 // LinkLocalUnicastIP reports whether ip is a link-local unicast address. 189 - func LinkLocalUnicastIP(ip cue.Value) bool { 190 - return netGetIP(ip).IsLinkLocalUnicast() 215 + func LinkLocalUnicastIP(ip cue.Value) (bool, error) { 216 + goip, err := netGetIP(ip) 217 + if err != nil { 218 + return false, err 219 + } 220 + return goip.IsLinkLocalUnicast(), nil 191 221 } 192 222 193 223 // GlobalUnicastIP reports whether ip is a global unicast address. ··· 196 226 // identification as defined in RFC 1122, RFC 4632 and RFC 4291 with the 197 227 // exception of IPv4 directed broadcast addresses. It returns true even if ip is 198 228 // in IPv4 private address space or local IPv6 unicast address space. 199 - func GlobalUnicastIP(ip cue.Value) bool { 200 - return netGetIP(ip).IsGlobalUnicast() 229 + func GlobalUnicastIP(ip cue.Value) (bool, error) { 230 + goip, err := netGetIP(ip) 231 + if err != nil { 232 + return false, err 233 + } 234 + return goip.IsGlobalUnicast(), nil 201 235 } 202 236 203 237 // UnspecifiedIP reports whether ip is an unspecified address, either the IPv4 204 238 // address "0.0.0.0" or the IPv6 address "::". 205 - func UnspecifiedIP(ip cue.Value) bool { 206 - return netGetIP(ip).IsUnspecified() 239 + func UnspecifiedIP(ip cue.Value) (bool, error) { 240 + goip, err := netGetIP(ip) 241 + if err != nil { 242 + return false, err 243 + } 244 + return goip.IsUnspecified(), nil 207 245 } 208 246 209 247 // ToIP4 converts a given IP address, which may be a string or a list, to its 210 248 // 4-byte representation. 211 249 func ToIP4(ip cue.Value) ([]uint, error) { 212 - ipdata := netGetIP(ip) 213 - if !ipdata.IsValid() { 214 - return nil, fmt.Errorf("invalid IP %q", ip) 250 + ipdata, err := netGetIP(ip) 251 + if err != nil { 252 + return nil, err 215 253 } 216 254 if !ipdata.Is4() { 217 255 return nil, fmt.Errorf("cannot convert %q to IPv4", ipdata) ··· 223 261 // ToIP16 converts a given IP address, which may be a string or a list, to its 224 262 // 16-byte representation. 225 263 func ToIP16(ip cue.Value) ([]uint, error) { 226 - ipdata := netGetIP(ip) 227 - if !ipdata.IsValid() { 228 - return nil, fmt.Errorf("invalid IP %q", ip) 264 + ipdata, err := netGetIP(ip) 265 + if err != nil { 266 + return nil, err 229 267 } 230 268 as16 := ipdata.As16() 231 269 return netToList(as16[:]), nil ··· 238 276 // - IPv6 ("2001:db8::1"), if ip is a valid IPv6 address 239 277 // - the hexadecimal form of ip, without punctuation, if no other cases apply 240 278 func IPString(ip cue.Value) (string, error) { 241 - ipdata := netGetIP(ip) 242 - if !ipdata.IsValid() { 243 - return "", fmt.Errorf("invalid IP %q", ip) 279 + ipdata, err := netGetIP(ip) 280 + if err != nil { 281 + return "", err 244 282 } 245 283 return ipdata.String(), nil 246 284 } ··· 279 317 } 280 318 return netip.PrefixFrom(addr, prefix.Bits()).String(), nil 281 319 } 282 - ipdata := netGetIP(ip) 283 - if !ipdata.IsValid() { 284 - return "", fmt.Errorf("invalid IP %q", ip) 320 + ipdata, err := netGetIP(ip) 321 + if err != nil { 322 + return "", err 285 323 } 286 324 addr, err := netIPAdd(ipdata, offset) 287 325 if err != nil { ··· 357 395 358 396 // InCIDR reports whether an IP address is contained a CIDR subnet string. 359 397 func InCIDR(ip, cidr cue.Value) (bool, error) { 360 - ipAddr := netGetIP(ip) 361 - if !ipAddr.IsValid() { 362 - return false, fmt.Errorf("invalid IP %q", ip) 398 + ipAddr, err := netGetIP(ip) 399 + if err != nil { 400 + return false, err 363 401 } 364 402 365 403 prefix, err := netGetIPCIDR(cidr) ··· 376 414 // 377 415 // The addresses may be strings or lists of bytes. 378 416 func CompareIP(ip1, ip2 cue.Value) (int, error) { 379 - addr1 := netGetIP(ip1) 380 - if !addr1.IsValid() { 381 - return 0, fmt.Errorf("invalid IP %q", ip1) 417 + addr1, err := netGetIP(ip1) 418 + if err != nil { 419 + return 0, err 382 420 } 383 - addr2 := netGetIP(ip2) 384 - if !addr2.IsValid() { 385 - return 0, fmt.Errorf("invalid IP %q", ip2) 421 + addr2, err := netGetIP(ip2) 422 + if err != nil { 423 + return 0, err 386 424 } 387 425 return addr1.Compare(addr2), nil 388 426 }
+10 -10
pkg/net/pkg.go
··· 78 78 Func: func(c *pkg.CallCtxt) { 79 79 ip := c.Value(0) 80 80 if c.Do() { 81 - c.Ret = IPv4(ip) 81 + c.Ret, c.Err = IPv4(ip) 82 82 } 83 83 }, 84 84 }, { ··· 90 90 Func: func(c *pkg.CallCtxt) { 91 91 ip := c.Value(0) 92 92 if c.Do() { 93 - c.Ret = IPv6(ip) 93 + c.Ret, c.Err = IPv6(ip) 94 94 } 95 95 }, 96 96 }, { ··· 102 102 Func: func(c *pkg.CallCtxt) { 103 103 ip := c.Value(0) 104 104 if c.Do() { 105 - c.Ret = IP(ip) 105 + c.Ret, c.Err = IP(ip) 106 106 } 107 107 }, 108 108 }, { ··· 126 126 Func: func(c *pkg.CallCtxt) { 127 127 ip := c.Value(0) 128 128 if c.Do() { 129 - c.Ret = LoopbackIP(ip) 129 + c.Ret, c.Err = LoopbackIP(ip) 130 130 } 131 131 }, 132 132 }, { ··· 138 138 Func: func(c *pkg.CallCtxt) { 139 139 ip := c.Value(0) 140 140 if c.Do() { 141 - c.Ret = MulticastIP(ip) 141 + c.Ret, c.Err = MulticastIP(ip) 142 142 } 143 143 }, 144 144 }, { ··· 150 150 Func: func(c *pkg.CallCtxt) { 151 151 ip := c.Value(0) 152 152 if c.Do() { 153 - c.Ret = InterfaceLocalMulticastIP(ip) 153 + c.Ret, c.Err = InterfaceLocalMulticastIP(ip) 154 154 } 155 155 }, 156 156 }, { ··· 162 162 Func: func(c *pkg.CallCtxt) { 163 163 ip := c.Value(0) 164 164 if c.Do() { 165 - c.Ret = LinkLocalMulticastIP(ip) 165 + c.Ret, c.Err = LinkLocalMulticastIP(ip) 166 166 } 167 167 }, 168 168 }, { ··· 174 174 Func: func(c *pkg.CallCtxt) { 175 175 ip := c.Value(0) 176 176 if c.Do() { 177 - c.Ret = LinkLocalUnicastIP(ip) 177 + c.Ret, c.Err = LinkLocalUnicastIP(ip) 178 178 } 179 179 }, 180 180 }, { ··· 186 186 Func: func(c *pkg.CallCtxt) { 187 187 ip := c.Value(0) 188 188 if c.Do() { 189 - c.Ret = GlobalUnicastIP(ip) 189 + c.Ret, c.Err = GlobalUnicastIP(ip) 190 190 } 191 191 }, 192 192 }, { ··· 198 198 Func: func(c *pkg.CallCtxt) { 199 199 ip := c.Value(0) 200 200 if c.Do() { 201 - c.Ret = UnspecifiedIP(ip) 201 + c.Ret, c.Err = UnspecifiedIP(ip) 202 202 } 203 203 }, 204 204 }, {
+6 -6
pkg/net/testdata/compareip.txtar
··· 36 36 t20: net.CompareIP("invalid1", "invalid2") 37 37 -- out/net-v3 -- 38 38 Errors: 39 - t18: error in call to net.CompareIP: invalid IP "invalid": 39 + t18: error in call to net.CompareIP: ParseAddr("invalid"): unable to parse IP: 40 40 ./in.cue:33:6 41 - t19: error in call to net.CompareIP: invalid IP "invalid": 41 + t19: error in call to net.CompareIP: ParseAddr("invalid"): unable to parse IP: 42 42 ./in.cue:34:6 43 - t20: error in call to net.CompareIP: invalid IP "invalid1": 43 + t20: error in call to net.CompareIP: ParseAddr("invalid1"): unable to parse IP: 44 44 ./in.cue:35:6 45 45 46 46 Result: ··· 74 74 t17: 0 75 75 76 76 // Error cases 77 - t18: _|_ // t18: error in call to net.CompareIP: invalid IP "invalid" 78 - t19: _|_ // t19: error in call to net.CompareIP: invalid IP "invalid" 79 - t20: _|_ // t20: error in call to net.CompareIP: invalid IP "invalid1" 77 + t18: _|_ // t18: error in call to net.CompareIP: ParseAddr("invalid"): unable to parse IP 78 + t19: _|_ // t19: error in call to net.CompareIP: ParseAddr("invalid"): unable to parse IP 79 + t20: _|_ // t20: error in call to net.CompareIP: ParseAddr("invalid1"): unable to parse IP
+15 -13
pkg/net/testdata/gen.txtar
··· 56 56 t47: net.AddIPCIDR("255.0.0.0/8", 1) 57 57 -- out/net-v3 -- 58 58 Errors: 59 - t20c: invalid value 123 (does not satisfy net.IP): 59 + t20b: invalid value 123 (does not satisfy net.IPCIDR): error in call to net.IPCIDR: invalid type int for IP CIDR: 60 + ./in.cue:23:7 61 + t20c: invalid value 123 (does not satisfy net.IP): error in call to net.IP: invalid type int for IP address: 60 62 ./in.cue:24:7 61 - t20d: invalid value 123 (does not satisfy net.IPv4): 63 + t20d: invalid value 123 (does not satisfy net.IPv4): error in call to net.IPv4: invalid type int for IP address: 62 64 ./in.cue:25:7 63 - t20e: invalid value 123 (does not satisfy net.IPv6): 65 + t20e: invalid value 123 (does not satisfy net.IPv6): error in call to net.IPv6: invalid type int for IP address: 64 66 ./in.cue:26:7 65 - t25: invalid value "2001:db8::1234567" (does not satisfy net.IPv6): 67 + t25: invalid value "2001:db8::1234567" (does not satisfy net.IPv6): error in call to net.IPv6: ParseAddr("2001:db8::1234567"): each group must have 4 or less digits (at "1234567"): 66 68 ./in.cue:31:6 67 69 ./in.cue:31:17 68 70 t30: invalid value "%" (does not satisfy net.URL): error in call to net.URL: parse "%": invalid URL escape "%": ··· 74 76 t34: invalid value "%" (does not satisfy net.AbsURL): error in call to net.AbsURL: parse "%": invalid URL escape "%": 75 77 ./in.cue:40:6 76 78 ./in.cue:40:19 77 - t9: invalid value "23.23.23.2333" (does not satisfy net.IPv4): 79 + t9: invalid value "23.23.23.2333" (does not satisfy net.IPv4): error in call to net.IPv4: ParseAddr("23.23.23.2333"): IPv4 field has value >255: 78 80 ./in.cue:11:6 79 81 ./in.cue:11:17 80 82 t7: error in call to net.JoinHostPort: invalid host [192, 30, 4]: ··· 87 89 t27: invalid value "23.23.23.23" (does not satisfy net.IPv6): 88 90 ./in.cue:33:6 89 91 ./in.cue:33:19 90 - t39: error in call to net.AddIP: invalid IP "invalid ip": 92 + t39: error in call to net.AddIP: ParseAddr("invalid ip"): unable to parse IP: 91 93 ./in.cue:45:6 92 94 t40: error in call to net.AddIP: IP address arithmetic resulted in out-of-range address (underflow): 93 95 ./in.cue:46:6 ··· 109 111 t6: "192.30.4.2:80" 110 112 t7: _|_ // t7: error in call to net.JoinHostPort: invalid host [192, 30, 4] 111 113 t8: true 112 - t9: _|_ // t9: invalid value "23.23.23.2333" (does not satisfy net.IPv4) 114 + t9: _|_ // t9: invalid value "23.23.23.2333" (does not satisfy net.IPv4): t9: error in call to net.IPv4: ParseAddr("23.23.23.2333"): IPv4 field has value >255 113 115 t10: true 114 116 t11: true 115 117 t12: false ··· 121 123 t18: true 122 124 t19: true 123 125 t20: _|_ // t20: error in call to net.IPCIDR: netip.ParsePrefix("172.16.12.3"): no '/' 124 - t20b: 123 125 - t20c: _|_ // t20c: invalid value 123 (does not satisfy net.IP) 126 - t20d: _|_ // t20d: invalid value 123 (does not satisfy net.IPv4) 127 - t20e: _|_ // t20e: invalid value 123 (does not satisfy net.IPv6) 126 + t20b: _|_ // t20b: invalid value 123 (does not satisfy net.IPCIDR): t20b: error in call to net.IPCIDR: invalid type int for IP CIDR 127 + t20c: _|_ // t20c: invalid value 123 (does not satisfy net.IP): t20c: error in call to net.IP: invalid type int for IP address 128 + t20d: _|_ // t20d: invalid value 123 (does not satisfy net.IPv4): t20d: error in call to net.IPv4: invalid type int for IP address 129 + t20e: _|_ // t20e: invalid value 123 (does not satisfy net.IPv6): t20e: error in call to net.IPv6: invalid type int for IP address 128 130 t21: "foo%2Fbar" 129 131 t22: "foo/bar" 130 132 t23: "f%25o" 131 133 t24: "f%o" 132 - t25: _|_ // t25: invalid value "2001:db8::1234567" (does not satisfy net.IPv6) 134 + t25: _|_ // t25: invalid value "2001:db8::1234567" (does not satisfy net.IPv6): t25: error in call to net.IPv6: ParseAddr("2001:db8::1234567"): each group must have 4 or less digits (at "1234567") 133 135 t26: true 134 136 t27: _|_ // t27: invalid value "23.23.23.23" (does not satisfy net.IPv6) 135 137 t28: true ··· 143 145 t36: "127.0.0.3/8" 144 146 t37: "2001:db8::1" 145 147 t38: "2001:db8::2/64" 146 - t39: _|_ // t39: error in call to net.AddIP: invalid IP "invalid ip" 148 + t39: _|_ // t39: error in call to net.AddIP: ParseAddr("invalid ip"): unable to parse IP 147 149 t40: _|_ // t40: error in call to net.AddIP: IP address arithmetic resulted in out-of-range address (underflow) 148 150 t41: _|_ // t41: error in call to net.AddIP: IP address arithmetic resulted in out-of-range address (overflow) 149 151 t42: "::ffff:127.0.0.2"
+4 -4
pkg/net/testdata/incidr.txtar
··· 38 38 v4: "2001:db8::1" & net.InCIDR("2001:db8::/32") 39 39 -- out/net-v3 -- 40 40 Errors: 41 - t15: error in call to net.InCIDR: invalid IP "invalid": 41 + t15: error in call to net.InCIDR: ParseAddr("invalid"): unable to parse IP: 42 42 ./in.cue:28:6 43 43 t16: error in call to net.InCIDR: netip.ParsePrefix("invalid"): no '/': 44 44 ./in.cue:29:6 45 45 t17: error in call to net.InCIDR: netip.ParsePrefix("192.168.1.0"): no '/': 46 46 ./in.cue:30:6 47 - t18: error in call to net.InCIDR: invalid IP "192.168.1.0/24": 47 + t18: error in call to net.InCIDR: ParseAddr("192.168.1.0/24"): unexpected character (at "/24"): 48 48 ./in.cue:31:6 49 49 v2: invalid value "10.0.0.1" (does not satisfy net.InCIDR("192.168.1.0/24")): 50 50 ./in.cue:35:18 ··· 77 77 t14: true 78 78 79 79 // Error cases 80 - t15: _|_ // t15: error in call to net.InCIDR: invalid IP "invalid" 80 + t15: _|_ // t15: error in call to net.InCIDR: ParseAddr("invalid"): unable to parse IP 81 81 t16: _|_ // t16: error in call to net.InCIDR: netip.ParsePrefix("invalid"): no '/' 82 82 t17: _|_ // t17: error in call to net.InCIDR: netip.ParsePrefix("192.168.1.0"): no '/' 83 - t18: _|_ // t18: error in call to net.InCIDR: invalid IP "192.168.1.0/24" 83 + t18: _|_ // t18: error in call to net.InCIDR: ParseAddr("192.168.1.0/24"): unexpected character (at "/24") 84 84 85 85 // Validator usage - IP is validated against a CIDR constraint 86 86 v1: "192.168.1.50"