Skip to content

Commit 28c5b4a

Browse files
committed
Merge #744
744: Mark and document pty::ptsname() as unsafe r=asomers a=nelsonjchen On some platforms, `ptsname()` mutates global variables and mutating global variables is always considered `unsafe` by Rust. Reference: #742 (comment)
2 parents 3b4fb07 + 505bed3 commit 28c5b4a

File tree

3 files changed

+22
-14
lines changed

3 files changed

+22
-14
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4545
- `MapFlags`, `MmapAdvise`, and `MsFlags` expose some more variants and only
4646
officially-supported variants are provided for each target.
4747
([#731](https://github.com/nix-rust/nix/pull/731))
48+
- Marked `pty::ptsname` function as `unsafe`
49+
([#744](https://github.com/nix-rust/nix/pull/744))
4850

4951
# Fixed
5052
- Fix compilation and tests for OpenBSD targets

src/pty.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub fn grantpt(fd: &PtyMaster) -> Result<()> {
100100
/// unlockpt(&master_fd)?;
101101
///
102102
/// // Get the name of the slave
103-
/// let slave_name = ptsname(&master_fd)?;
103+
/// let slave_name = unsafe { ptsname(&master_fd) }?;
104104
///
105105
/// // Try to open the slave
106106
/// # #[allow(unused_variables)]
@@ -125,20 +125,26 @@ pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
125125
/// [ptsname(3)](http://man7.org/linux/man-pages/man3/ptsname.3.html))
126126
///
127127
/// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master
128-
/// referred to by `fd`. Note that this function is *not* threadsafe. For that see `ptsname_r()`.
128+
/// referred to by `fd`.
129129
///
130130
/// This value is useful for opening the slave pty once the master has already been opened with
131131
/// `posix_openpt()`.
132+
///
133+
/// # Safety
134+
///
135+
/// `ptsname()` mutates global variables and is *not* threadsafe.
136+
/// Mutating global variables is always considered `unsafe` by Rust and this
137+
/// function is marked as `unsafe` to reflect that.
138+
///
139+
/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`.
132140
#[inline]
133-
pub fn ptsname(fd: &PtyMaster) -> Result<String> {
134-
let name_ptr = unsafe { libc::ptsname(fd.as_raw_fd()) };
141+
pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
142+
let name_ptr = libc::ptsname(fd.as_raw_fd());
135143
if name_ptr.is_null() {
136144
return Err(Error::last().into());
137145
}
138146

139-
let name = unsafe {
140-
CStr::from_ptr(name_ptr)
141-
};
147+
let name = CStr::from_ptr(name_ptr);
142148
Ok(name.to_string_lossy().into_owned())
143149
}
144150

@@ -187,7 +193,7 @@ pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
187193

188194
/// Create a new pseudoterminal, returning the slave and master file descriptors
189195
/// in `OpenptyResult`
190-
/// (see [openpty](http://man7.org/linux/man-pages/man3/openpty.3.html)).
196+
/// (see [openpty](http://man7.org/linux/man-pages/man3/openpty.3.html)).
191197
///
192198
/// If `winsize` is not `None`, the window size of the slave will be set to
193199
/// the values in `winsize`. If `termios` is not `None`, the pseudoterminal's

test/test_pty.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn test_ptsname_equivalence() {
3535
assert!(master_fd.as_raw_fd() > 0);
3636

3737
// Get the name of the slave
38-
let slave_name = ptsname(&master_fd).unwrap();
38+
let slave_name = unsafe { ptsname(&master_fd) }.unwrap() ;
3939
let slave_name_r = ptsname_r(&master_fd).unwrap();
4040
assert_eq!(slave_name, slave_name_r);
4141
}
@@ -53,8 +53,8 @@ fn test_ptsname_copy() {
5353
assert!(master_fd.as_raw_fd() > 0);
5454

5555
// Get the name of the slave
56-
let slave_name1 = ptsname(&master_fd).unwrap();
57-
let slave_name2 = ptsname(&master_fd).unwrap();
56+
let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap();
57+
let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap();
5858
assert!(slave_name1 == slave_name2);
5959
// Also make sure that the string was actually copied and they point to different parts of
6060
// memory.
@@ -92,8 +92,8 @@ fn test_ptsname_unique() {
9292
assert!(master2_fd.as_raw_fd() > 0);
9393

9494
// Get the name of the slave
95-
let slave_name1 = ptsname(&master1_fd).unwrap();
96-
let slave_name2 = ptsname(&master2_fd).unwrap();
95+
let slave_name1 = unsafe { ptsname(&master1_fd) }.unwrap();
96+
let slave_name2 = unsafe { ptsname(&master2_fd) }.unwrap();
9797
assert!(slave_name1 != slave_name2);
9898
}
9999

@@ -116,7 +116,7 @@ fn test_open_ptty_pair() {
116116
unlockpt(&master_fd).expect("unlockpt failed");
117117

118118
// Get the name of the slave
119-
let slave_name = ptsname(&master_fd).expect("ptsname failed");
119+
let slave_name = unsafe { ptsname(&master_fd) }.expect("ptsname failed");
120120

121121
// Open the slave device
122122
let slave_fd = open(Path::new(&slave_name), O_RDWR, stat::Mode::empty()).unwrap();

0 commit comments

Comments
 (0)