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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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