diff --git a/baked_in.go b/baked_in.go index 80e02779..df2cfa58 100644 --- a/baked_in.go +++ b/baked_in.go @@ -2916,7 +2916,32 @@ func isHostnameRFC952(fl FieldLevel) bool { } func isHostnameRFC1123(fl FieldLevel) bool { - return hostnameRegexRFC1123().MatchString(fl.Field().String()) + val := fl.Field().String() + if !hostnameRegexRFC1123().MatchString(val) { + return false + } + // Per RFC 1123 Section 2.1, host names cannot have the dotted-decimal + // format #.#.#.# unless they represent a valid IP address. If the value + // has four dot-separated numeric parts, verify that it parses as a valid IP. + if looksLikeIPv4(val) { + return net.ParseIP(val) != nil + } + return true +} + +// looksLikeIPv4 reports whether s consists of exactly four dot-separated +// numeric components (e.g. "192.168.0.1", "277.168.0.1"). +func looksLikeIPv4(s string) bool { + parts := 1 + for i := 0; i < len(s); i++ { + c := s[i] + if c == '.' { + parts++ + } else if c < '0' || c > '9' { + return false + } + } + return parts == 4 } func isHostnameLabel(fl FieldLevel) bool { diff --git a/validator_test.go b/validator_test.go index ffaf582f..2b5adcf9 100644 --- a/validator_test.go +++ b/validator_test.go @@ -11248,6 +11248,20 @@ func TestHostnameRFC1123Validation(t *testing.T) { {"example.", false}, {"test_example", false}, {"192.168.0.1", true}, + {"277.168.0.1", false}, + {"999.999.999.999", false}, + {"1.2.3.256", false}, + {"256.0.0.1", false}, + {"0.0.0.0", true}, + {"255.255.255.255", true}, + {"3com.com", true}, + {"1and1.com", true}, + {"7-eleven.com", true}, + {"1234", true}, + {"12345", true}, + {"1.2.3", true}, + {"1.2.3.4.5", true}, + {"192.168.0.a", true}, {"email@example.com", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false}, @@ -11308,6 +11322,13 @@ func TestHostnameRFC1123AliasValidation(t *testing.T) { {"example.", false}, {"test_example", false}, {"192.168.0.1", true}, + {"277.168.0.1", false}, + {"999.999.999.999", false}, + {"1.2.3.256", false}, + {"0.0.0.0", true}, + {"255.255.255.255", true}, + {"1.2.3", true}, + {"1234", true}, {"email@example.com", false}, {"2001:cdba:0000:0000:0000:0000:3257:9652", false}, {"2001:cdba:0:0:0:0:3257:9652", false},