Go version
go version go1.24.4 openbsd/amd64
Output of go env
in your module/workspace:
AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/jrick/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/jrick/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2338133049=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='openbsd'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/home/jrick/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='openbsd'
GOPATH='/home/jrick/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/jrick/src/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/jrick/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/home/jrick/src/go/pkg/tool/openbsd_amd64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
ParseAddr with the address string "fe80::1234:1%iwx0/104" returns an Addr that strings back to the same input, while I would expect this to fail (as ParseAddr does for inputs with prefixes without zones).
https://go.dev/play/p/sBg1XwXT-q3
This unexpected behavior occurred while attempting to write a single function that handled parsing both plain IPs and CIDR masked IPs, with implicit full masks when the bits were not specified, due to my function first calling netip.ParseAddr and returning without error if that succeeds, before falling back to netip.ParsePrefix (which does error on the very same input: https://go.dev/play/p/pcjj0dEEmhV).
What did you see happen?
No error.
What did you expect to see?
ParseAddr errors if input contains both zone and prefix, as it is documented to error if it includes a prefix (this does work as documented without a zone).
Comment From: jrick
And I realize the /104 is silly, originally before rewriting this test case that was a 10/8 as a 4-in-6, that i slapped a zone onto.
Comment From: gabyhelp
Related Issues
- net/ip: ParsePrefix with IPv6 zone should return an error #51899 (closed)
- netip.ParsePrefix must not silently accept ip4in6 address #53135 (closed)
- net: Unable to reliably distinguish IPv4-mapped-IPv6 addresses from regular IPv4 addresses #37921
- net: `ParseIP` returns nil instead of IP to a seemingly valid IPv6 #69752 (closed)
- net/netip: ParseAddr should reject invalid zone #71362
- net: inconsistent behaviour with IPv4-mapped IPv6 CIDRs #51906
- net: ipv6 address parsing allows extra 0 #57760 (closed)
- net/netip: ParseAddr gives different values with same input #50111 (closed)
- net/netip: Prefix, the range of bits for 4in6 addresses must be restricted to [96,128] #53153
- net/netip: ParsePrefix allows "+", "-", leading zeroes in prefix length #63850 (closed)
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: jrick
Oh it gets worse: https://go.dev/play/p/FMKe53qtWat
Unlike ParsePrefix which catches the out-of-range prefix, ParseAddr here does not.
Comment From: jrick
The only explanation I can think of is that perhaps slashes in zones are legal, as that is how it is parsed (by evidence of what Zone() on the above returns: https://go.dev/play/p/vc_SbupuOiE).
~Yet, it seems to be parsed as a real prefix at some point, as anything following the slash must be a legal numeric character.~ nope anything goes, I probably edited my ParsePrefix playground link trying this out.
Comment From: jrick
This is unfortunate but probably correct, per rfc6874:
According to IPv6 Scoped Address syntax [RFC4007], a zone identifier is attached to the textual representation of an IPv6 address by concatenating "%" followed by
, where is a string identifying the zone of the address. However, the IPv6 Scoped Address Architecture specification gives no precise definition of the character set allowed in . There are no rules or de facto standards for this. For example, the first Ethernet interface in a host might be called %0, %1, %en1, %eth0, or whatever the implementer happened to choose.