rust-lang / rust-lang/rust

Documentation should be clearer about lack of support for IPv4-mapped IPv6 addresses in helper methods

Open Beginner friendly
#161,797 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

A-docs T-libs
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Location (URL)

https://doc.rust-lang.org/std/net/enum.IpAddr.html
https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html

Summary

There has been past discussion about whether Rust should support IPv4-mapped IPv6 addresses, and I don't want to raise that issue again. But the current behaviour has some footguns that I think should be documented better.

For example, I think it's reasonable to write a function such as:

/// Ensure that we don't make TCP connections to loopback addresses.
fn connect_if_not_loopback(s: SocketAddr) -> std::io::Result<Option<TcpStream>> {
    if s.ip().is_loopback() {
        return Ok(None);
    }

    Ok(Some(TcpStream::connect(s)?))
}

and it would be reasonable to expect that it would prevent connections to loopback addresses. And there isn't anything in IpAddr that would suggest otherwise.

But since Ipv6Addr::is_loopback() does not handle IPv4-mapped IPv6 addresses, this code is broken, and may lead to security issues in code where the author wasn't knowledgeable of IPv4-mapped IPv6 addresses.

For example:

let localhost = IpAddr::V6(Ipv4Addr::LOCALHOST.to_ipv6_mapped());
// We expect this to return `None`, but it connects to the loopback address and returns `Some`.
// This assertion panics.
assert!(connect_if_not_loopback(SocketAddr::new(localhost, 9000)).unwrap().is_none());

The correct code (AFAIK) should use s.ip().to_canonical().is_loopback(), but this isn't clear from the documentation. And this isn't an issue for just is_loopback(), but also other methods like is_unspecified() and the various nightly methods.

There is some top-level documentation in Ipv6Addr, but it doesn't mention to_canonical() at all and is easy to miss.

So I think it would be helpful (and remove a footgun) for IpAddr and Ipv6Addr if the helper is_foo() methods had a sentence explaining that they don't handle IPv4-mapped IPv6 addresses, and linked to a paragraph for how to handle them properly.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the IpAddr and Ipv6Addr documentation pages named in the issue, including the “embedding IPv4 addresses” section and the listed is_foo() helper methods. Clarify that these helpers do not handle IPv4-mapped IPv6 addresses, and link to the documented canonicalization approach. Done means the affected helper documentation clearly explains the limitation and how to handle mapped addresses.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
documentation, networking
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.