Repository: rust-lang/rust
Pull request: Fix SGX delayed host lookup via ToSocketAddr

<!-- homu-ignore:start -->
*[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/152851)*
<!-- homu-ignore:end -->

rust-lang/rust#146541 introduced a regression in the `x86_64-fortanix-unknown-sgx` target, where arguments to TcpStream::connect and TcpListener::bind are no longer being passed down correctly to the underlying platform, resulting in connection/bind failures

* Add a test for the desired behavior (this test passes on Rust 1.33 through 1.91)
* Refactor lookup_host logic again

Fixes rust-lang/rust#152848

cc @joboet 

Changed files:
filename: library/std/src/net/socket_addr.rs
patch: @@ -189,11 +189,6 @@ impl ToSocketAddrs for (Ipv6Addr, u16) {
     }
 }
 
-fn lookup_host(host: &str, port: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
-    let addrs = crate::sys::net::lookup_host(host, port)?;
-    Ok(Vec::from_iter(addrs).into_iter())
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToSocketAddrs for (&str, u16) {
     type Iter = vec::IntoIter<SocketAddr>;
@@ -207,7 +202,7 @@ impl ToSocketAddrs for (&str, u16) {
         }
 
         // Otherwise, make the system look it up.
-        lookup_host(host, port)
+        crate::sys::net::lookup_host(host, port).map(|addrs| Vec::from_iter(addrs).into_iter())
     }
 }
 
@@ -229,16 +224,8 @@ impl ToSocketAddrs for str {
             return Ok(vec![addr].into_iter());
         }
 
-        // Otherwise, split the string by ':' and convert the second part to u16...
-        let Some((host, port_str)) = self.rsplit_once(':') else {
-            return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid socket address"));
-        };
-        let Ok(port) = port_str.parse::<u16>() else {
-            return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid port value"));
-        };
-
-        // ... and make the system look up the host.
-        lookup_host(host, port)
+        // Otherwise, make the system look it up.
+        crate::sys::net::lookup_host_string(self).map(|addrs| Vec::from_iter(addrs).into_iter())
     }
 }
 

filename: library/std/src/sys/net/connection/mod.rs
patch: @@ -59,3 +59,22 @@ where
         None => Err(Error::NO_ADDRESSES),
     }
 }
+
+// Default implementation, may be overridden by platform-specific implementations.
+#[cfg(not(all(target_vendor = "fortanix", target_env = "sgx")))]
+pub(crate) fn lookup_host_string(
+    addr: &str,
+) -> crate::io::Result<impl Iterator<Item = crate::net::SocketAddr>> {
+    use crate::io;
+
+    // Split the string by ':' and convert the second part to u16...
+    let Some((host, port_str)) = addr.rsplit_once(':') else {
+        return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid socket address"));
+    };
+    let Ok(port) = port_str.parse::<u16>() else {
+        return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid port value"));
+    };
+
+    // ... and make the system look up the host.
+    crate::sys::net::lookup_host(host, port)
+}

filename: library/std/src/sys/net/connection/sgx.rs
patch: @@ -506,9 +506,23 @@ impl Iterator for LookupHost {
     }
 }
 
+pub(crate) fn lookup_host_string(addr: impl Into<String>) -> io::Result<LookupHost> {
+    Err(io::Error::new(io::ErrorKind::Uncategorized, NonIpSockAddr { host: addr.into() }))
+}
+
 pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
-    Err(io::Error::new(
-        io::ErrorKind::Uncategorized,
-        NonIpSockAddr { host: format!("{host}:{port}") },
-    ))
+    lookup_host_string(format!("{host}:{port}"))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn unparseable_sockaddr() {
+        let addr = "local";
+        let error = addr.to_socket_addrs().unwrap_err();
+        let non_ip_addr = error.downcast::<NonIpSockAddr>().unwrap();
+        assert_eq!(addr, non_ip_addr.host);
+    }
 }