-
Notifications
You must be signed in to change notification settings - Fork 17.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/vet: flag using %s:%d to construct network addresses #28308
Comments
This definitely checks the correctness and frequency requirements for a vet check - the issue leads to bugs, and it happens often. However, I'm not sure if it ticks off the precision requirement. If the check simply inspects the syntax tree, it could be prone to false positives or negatives. Dominik proposes a slightly different approach for his tooling in dominikh/go-tools#358, for example. |
See: golang/go#28308, dominikh/go-tools#358 and others.
Using fmt.Sprintf("%s:%d", host, port) or similar to construct network address strings can to problems when dealing with IPv6 addresses. However, net.JoinHostPort formats IPv6 in the correct [host]:port notation, for example [fe80::a46c:bcff:feed:a481]:8080 For consistency, also use the same function in places where it's obvious we're dealing with IPv4 addresses. Also see golang/go#28308 Found using semgrep using the hostport.yml rule from https://github.com/dgryski/semgrep-go Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Using fmt.Sprintf("%s:%d", host, port) or similar to construct network address strings can to problems when dealing with IPv6 addresses. However, net.JoinHostPort formats IPv6 in the correct [host]:port notation, for example [fe80::a46c:bcff:feed:a481]:8080 For consistency, also use the same function in places where it's obvious we're dealing with IPv4 addresses. Also see golang/go#28308 Found using semgrep using the hostport.yml rule from https://github.com/dgryski/semgrep-go Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
[ upstream commit 070214f ] Using fmt.Sprintf("%s:%d", host, port) or similar to construct network address strings can to problems when dealing with IPv6 addresses. However, net.JoinHostPort formats IPv6 in the correct [host]:port notation, for example [fe80::a46c:bcff:feed:a481]:8080 For consistency, also use the same function in places where it's obvious we're dealing with IPv4 addresses. Also see golang/go#28308 Found using semgrep using the hostport.yml rule from https://github.com/dgryski/semgrep-go Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Paul Chaignon <paul@cilium.io>
[ upstream commit 070214f ] Using fmt.Sprintf("%s:%d", host, port) or similar to construct network address strings can to problems when dealing with IPv6 addresses. However, net.JoinHostPort formats IPv6 in the correct [host]:port notation, for example [fe80::a46c:bcff:feed:a481]:8080 For consistency, also use the same function in places where it's obvious we're dealing with IPv4 addresses. Also see golang/go#28308 Found using semgrep using the hostport.yml rule from https://github.com/dgryski/semgrep-go Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Paul Chaignon <paul@cilium.io>
I agree that you want to look for fmt.Sprint output feeding into net.Dial, not variable names. |
It also seems like you'd want to find x+":"+z as a Dial argument. So it sounds like the next step would be to implement a check and see how well it does on the three vet criteria from cmd/vet/README. Does anyone want to do that? |
This proposal has been added to the active column of the proposals project |
You may want to look other variants of the format string: |
@rsc I can try making a checker for this. |
I grepped for |
I filed #44955 as a potential alternative to discuss: just accept %s:%d in Dial instead, at least for tcp and udp. |
Blocked on #44955. |
#44955 is retracted. Back to this. |
I don't see anyone objecting to adding this vet check. Are there any objections? |
Based on the discussion above, this proposal seems like a likely accept. |
No change in consensus, so accepted. 🎉 |
Change https://go.dev/cl/554495 mentions this issue: |
I recently diagnosed a bug in someone’s Go program where a user reported that they couldn’t get the program to connect, and it turned out the issue was that the programmer used
fmt.Sprintf("%s:%d", host, port)
instead ofnet.JoinHostPort
to construct a network address to pass tonet.Dial
: https://twitter.com/zekjur/status/1049642773278650368. The issue is subtle:net.JoinHostPort
correctly handles IPv6 address literals (e.g. 2001:4860:4860::8888), whereas fmt.Sprintf doesn’t.A very similar issue is to use
strings.Split
instead ofnet.SplitHostPort
.I noticed that both of these issues are fairly prevalent, likely because programmers aren’t that accustomed to using IPv6 literals yet, but I expect them to become more common as IPv6 adoption continues to grow.
I propose adding a vet check to flag using %s:%d format strings with arguments whose names contain port, addr, host, listen or bind. This heuristic will flag 12356 occurrences¹ I found on GitHub using BigQuery, and hopefully make programmers aware not only of net.JoinHostPort but also net.SplitHostPort, for which writing a check is significantly harder.
I can send a CL to implement this. Let me know what you think.
① The BigQuery query I used was:
The text was updated successfully, but these errors were encountered: