Skip to content

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

Description

@opara-tor

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions