Skip to content

Commit 9b46ae7

Browse files
authored
sort out possible mishandling of ipv4 vs v6 (#431)
1 parent f589245 commit 9b46ae7

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

openapi3/schema_formats.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"net"
66
"regexp"
7+
"strings"
78
)
89

910
const (
@@ -37,38 +38,37 @@ func DefineStringFormatCallback(name string, callback FormatCallback) {
3738
SchemaStringFormats[name] = Format{callback: callback}
3839
}
3940

40-
func validateIP(ip string) (*net.IP, error) {
41+
func validateIP(ip string) error {
4142
parsed := net.ParseIP(ip)
4243
if parsed == nil {
43-
return nil, &SchemaError{
44+
return &SchemaError{
4445
Value: ip,
4546
Reason: "Not an IP address",
4647
}
4748
}
48-
return &parsed, nil
49+
return nil
4950
}
5051

5152
func validateIPv4(ip string) error {
52-
parsed, err := validateIP(ip)
53-
if err != nil {
53+
if err := validateIP(ip); err != nil {
5454
return err
5555
}
5656

57-
if parsed.To4() == nil {
57+
if !(strings.Count(ip, ":") < 2) {
5858
return &SchemaError{
5959
Value: ip,
6060
Reason: "Not an IPv4 address (it's IPv6)",
6161
}
6262
}
6363
return nil
6464
}
65+
6566
func validateIPv6(ip string) error {
66-
parsed, err := validateIP(ip)
67-
if err != nil {
67+
if err := validateIP(ip); err != nil {
6868
return err
6969
}
7070

71-
if parsed.To4() != nil {
71+
if !(strings.Count(ip, ":") >= 2) {
7272
return &SchemaError{
7373
Value: ip,
7474
Reason: "Not an IPv6 address (it's IPv4)",

openapi3/schema_formats_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package openapi3
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestIssue430(t *testing.T) {
11+
schema := NewOneOfSchema(
12+
NewStringSchema().WithFormat("ipv4"),
13+
NewStringSchema().WithFormat("ipv6"),
14+
)
15+
16+
err := schema.Validate(context.Background())
17+
require.NoError(t, err)
18+
19+
data := map[string]bool{
20+
"127.0.1.1": true,
21+
22+
// https://stackoverflow.com/a/48519490/1418165
23+
24+
// v4
25+
"192.168.0.1": true,
26+
// "192.168.0.1:80" doesn't parse per net.ParseIP()
27+
28+
// v6
29+
"::FFFF:C0A8:1": false,
30+
"::FFFF:C0A8:0001": false,
31+
"0000:0000:0000:0000:0000:FFFF:C0A8:1": false,
32+
// "::FFFF:C0A8:1%1" doesn't parse per net.ParseIP()
33+
"::FFFF:192.168.0.1": false,
34+
// "[::FFFF:C0A8:1]:80" doesn't parse per net.ParseIP()
35+
// "[::FFFF:C0A8:1%1]:80" doesn't parse per net.ParseIP()
36+
}
37+
38+
for datum := range data {
39+
err = schema.VisitJSON(datum)
40+
require.Error(t, err, ErrOneOfConflict.Error())
41+
}
42+
43+
DefineIPv4Format()
44+
DefineIPv6Format()
45+
46+
for datum, isV4 := range data {
47+
err = schema.VisitJSON(datum)
48+
require.NoError(t, err)
49+
if isV4 {
50+
require.Nil(t, validateIPv4(datum), "%q should be IPv4", datum)
51+
require.NotNil(t, validateIPv6(datum), "%q should not be IPv6", datum)
52+
} else {
53+
require.NotNil(t, validateIPv4(datum), "%q should not be IPv4", datum)
54+
require.Nil(t, validateIPv6(datum), "%q should be IPv6", datum)
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)