@@ -74,16 +74,39 @@ pub struct Socket {
74
74
/// Store a `TcpStream` internally to take advantage of its niche optimizations on Unix platforms.
75
75
pub ( crate ) type Inner = std:: net:: TcpStream ;
76
76
77
- // The `sys` module must have access to the below three functions.
78
77
impl Socket {
78
+ /// # Safety
79
+ ///
80
+ /// The caller must ensure `raw` is a valid file descriptor/socket. NOTE:
81
+ /// this should really be marked `unsafe`, but this being an internal
82
+ /// function, often passed as mapping function, it's makes it very
83
+ /// inconvenient to mark it as `unsafe`.
79
84
pub ( crate ) fn from_raw ( raw : sys:: Socket ) -> Socket {
80
85
Socket {
81
- inner : sys:: socket_from_raw ( raw) ,
86
+ inner : unsafe {
87
+ // SAFETY: the caller must ensure that `raw` is a valid file
88
+ // descriptor, but when it isn't it could return I/O errors, or
89
+ // potentially close a fd it doesn't own. All of that isn't
90
+ // memory unsafe, so it's not desired but never memory unsafe or
91
+ // causes UB.
92
+ //
93
+ // However there is one exception. We use `TcpStream` to
94
+ // represent the `Socket` internally (see `Inner` type),
95
+ // `TcpStream` has a layout optimisation that doesn't allow for
96
+ // negative file descriptors (as those are always invalid).
97
+ // Violating this assumption (fd never negative) causes UB,
98
+ // something we don't want. So check for that we have this
99
+ // `assert!`.
100
+ assert ! ( raw >= 0 , "tried to create a `Socket` with an invalid fd" ) ;
101
+ sys:: socket_from_raw ( raw)
102
+ } ,
82
103
}
83
104
}
105
+
84
106
pub ( crate ) fn as_raw ( & self ) -> sys:: Socket {
85
107
sys:: socket_as_raw ( & self . inner )
86
108
}
109
+
87
110
pub ( crate ) fn into_raw ( self ) -> sys:: Socket {
88
111
sys:: socket_into_raw ( self . inner )
89
112
}
0 commit comments