summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md11
-rw-r--r--src/macros.rs128
-rw-r--r--src/sys/event.rs25
-rw-r--r--src/sys/signal.rs18
-rw-r--r--src/sys/termios.rs119
5 files changed, 156 insertions, 145 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d311d144..1faf8f97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -43,17 +43,28 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Many more functions, mostly contructors, are now `const`.
(#[1476](https://github.com/nix-rust/nix/pull/1476))
+- `sys::event::KEvent::filter` now returns a `Result` instead of being
+ infalliable. The only cases where it will now return an error are cases
+ where it previously would've had undefined behavior.
+ (#[1484](https://github.com/nix-rust/nix/pull/1484))
+
### Fixed
- Added more errno definitions for better backwards compatibility with
Nix 0.21.0.
(#[1467](https://github.com/nix-rust/nix/pull/1467))
+- Fixed potential undefined behavior in `Signal::try_from` on some platforms.
+ (#[1484](https://github.com/nix-rust/nix/pull/1484))
+
### Removed
- Removed a couple of termios constants on redox that were never actually
supported.
(#[1483](https://github.com/nix-rust/nix/pull/1483))
+- Removed `nix::sys::signal::NSIG`. It was of dubious utility, and not correct
+ for all platforms.
+ (#[1484](https://github.com/nix-rust/nix/pull/1484))
## [0.22.0] - 9 July 2021
### Added
diff --git a/src/macros.rs b/src/macros.rs
index 7d6ac8df..927e7e7c 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -83,9 +83,9 @@ macro_rules! libc_bitflags {
macro_rules! libc_enum {
// Exit rule.
(@make_enum
+ name: $BitFlags:ident,
{
$v:vis
- name: $BitFlags:ident,
attrs: [$($attrs:tt)*],
entries: [$($entries:tt)*],
}
@@ -97,38 +97,98 @@ macro_rules! libc_enum {
}
};
+ // Exit rule including TryFrom
+ (@make_enum
+ name: $BitFlags:ident,
+ {
+ $v:vis
+ attrs: [$($attrs:tt)*],
+ entries: [$($entries:tt)*],
+ from_type: $repr:path,
+ try_froms: [$($try_froms:tt)*]
+ }
+ ) => {
+ $($attrs)*
+ #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+ $v enum $BitFlags {
+ $($entries)*
+ }
+ #[allow(unused_doc_comment)]
+ impl ::std::convert::TryFrom<$repr> for $BitFlags {
+ type Error = $crate::Error;
+ fn try_from(x: $repr) -> $crate::Result<Self> {
+ match x {
+ $($try_froms)*
+ _ => Err($crate::Error::EINVAL)
+ }
+ }
+ }
+ };
+
// Done accumulating.
(@accumulate_entries
+ name: $BitFlags:ident,
+ {
+ $v:vis
+ attrs: $attrs:tt,
+ },
+ $entries:tt,
+ $try_froms:tt;
+ ) => {
+ libc_enum! {
+ @make_enum
+ name: $BitFlags,
+ {
+ $v
+ attrs: $attrs,
+ entries: $entries,
+ }
+ }
+ };
+
+ // Done accumulating and want TryFrom
+ (@accumulate_entries
+ name: $BitFlags:ident,
{
$v:vis
- name: $BitFlags:ident,
attrs: $attrs:tt,
+ from_type: $repr:path,
},
- $entries:tt;
+ $entries:tt,
+ $try_froms:tt;
) => {
libc_enum! {
@make_enum
+ name: $BitFlags,
{
$v
- name: $BitFlags,
attrs: $attrs,
entries: $entries,
+ from_type: $repr,
+ try_froms: $try_froms
}
}
};
// Munch an attr.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
#[$attr:meta] $($tail:tt)*
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
#[$attr]
+ ],
+ [
+ $($try_froms)*
+ #[$attr]
];
$($tail)*
}
@@ -136,32 +196,47 @@ macro_rules! libc_enum {
// Munch last ident if not followed by a comma.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
$entry:ident
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
$entry = libc::$entry,
+ ],
+ [
+ $($try_froms)*
+ libc::$entry => Ok($BitFlags::$entry),
];
}
};
// Munch an ident; covers terminating comma case.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
- $entry:ident, $($tail:tt)*
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
+ $entry:ident,
+ $($tail:tt)*
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
$entry = libc::$entry,
+ ],
+ [
+ $($try_froms)*
+ libc::$entry => Ok($BitFlags::$entry),
];
$($tail)*
}
@@ -169,16 +244,24 @@ macro_rules! libc_enum {
// Munch an ident and cast it to the given type; covers terminating comma.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
- $entry:ident as $ty:ty, $($tail:tt)*
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
+ $entry:ident as $ty:ty,
+ $($tail:tt)*
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
$entry = libc::$entry as $ty,
+ ],
+ [
+ $($try_froms)*
+ libc::$entry as $ty => Ok($BitFlags::$entry),
];
$($tail)*
}
@@ -193,11 +276,34 @@ macro_rules! libc_enum {
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
+ {
+ $v
+ attrs: [$(#[$attr])*],
+ },
+ [],
+ [];
+ $($vals)*
+ }
+ };
+
+ // Entry rule including TryFrom
+ (
+ $(#[$attr:meta])*
+ $v:vis enum $BitFlags:ident {
+ $($vals:tt)*
+ }
+ impl TryFrom<$repr:path>
+ ) => {
+ libc_enum! {
+ @accumulate_entries
+ name: $BitFlags,
{
$v
- name: $BitFlags,
attrs: [$(#[$attr])*],
+ from_type: $repr,
},
+ [],
[];
$($vals)*
}
diff --git a/src/sys/event.rs b/src/sys/event.rs
index 1f4c1b41..c648f5eb 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -6,9 +6,9 @@ use crate::{Errno, Result};
use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
#[cfg(target_os = "netbsd")]
use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
+use std::convert::TryInto;
use std::os::unix::io::RawFd;
use std::ptr;
-use std::mem;
// Redefine kevent in terms of programmer-friendly enums and bitfields.
#[repr(C)]
@@ -76,6 +76,7 @@ libc_enum! {
EVFILT_VNODE,
EVFILT_WRITE,
}
+ impl TryFrom<type_of_event_filter>
}
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
@@ -233,8 +234,8 @@ impl KEvent {
self.kevent.ident
}
- pub fn filter(&self) -> EventFilter {
- unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
+ pub fn filter(&self) -> Result<EventFilter> {
+ self.kevent.filter.try_into()
}
pub fn flags(&self) -> EventFlag {
@@ -313,6 +314,8 @@ pub fn ev_set(ev: &mut KEvent,
#[test]
fn test_struct_kevent() {
+ use std::mem;
+
let udata : intptr_t = 12345;
let actual = KEvent::new(0xdead_beef,
@@ -322,10 +325,24 @@ fn test_struct_kevent() {
0x1337,
udata);
assert_eq!(0xdead_beef, actual.ident());
- assert_eq!(libc::EVFILT_READ, actual.filter() as type_of_event_filter);
+ let filter = actual.kevent.filter;
+ assert_eq!(libc::EVFILT_READ, filter);
assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
assert_eq!(0x1337, actual.data() as type_of_data);
assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
}
+
+#[test]
+fn test_kevent_filter() {
+ let udata : intptr_t = 12345;
+
+ let actual = KEvent::new(0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ 0x1337,
+ udata);
+ assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
+}
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index cbd5cfbe..e68ebf16 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -6,7 +6,6 @@
use crate::{Error, Result};
use crate::errno::Errno;
use crate::unistd::Pid;
-use std::convert::TryFrom;
use std::mem;
use std::fmt;
use std::str::FromStr;
@@ -71,6 +70,7 @@ libc_enum!{
target_os = "redox")))]
SIGINFO,
}
+ impl TryFrom<i32>
}
impl FromStr for Signal {
@@ -335,8 +335,6 @@ const SIGNALS: [Signal; 31] = [
SIGEMT,
SIGINFO];
-pub const NSIG: libc::c_int = 32;
-
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SignalIterator {
next: usize,
@@ -362,18 +360,6 @@ impl Signal {
}
}
-impl TryFrom<libc::c_int> for Signal {
- type Error = Error;
-
- fn try_from(signum: libc::c_int) -> Result<Signal> {
- if 0 < signum && signum < NSIG {
- Ok(unsafe { mem::transmute(signum) })
- } else {
- Err(Error::from(Errno::EINVAL))
- }
- }
-}
-
pub const SIGIOT : Signal = SIGABRT;
pub const SIGPOLL : Signal = SIGIO;
pub const SIGUNUSED : Signal = SIGSYS;
@@ -489,6 +475,8 @@ impl SigSet {
/// signal mask becomes pending, and returns the accepted signal.
#[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
pub fn wait(&self) -> Result<Signal> {
+ use std::convert::TryFrom;
+
let mut signum = mem::MaybeUninit::uninit();
let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index 1e4307e3..01d46080 100644
--- a/src/sys/termios.rs
+++ b/src/sys/termios.rs
@@ -152,11 +152,11 @@
//! # }
//! ```
use cfg_if::cfg_if;
-use crate::{Error, Result};
+use crate::Result;
use crate::errno::Errno;
use libc::{self, c_int, tcflag_t};
use std::cell::{Ref, RefCell};
-use std::convert::{From, TryFrom};
+use std::convert::From;
use std::mem;
use std::os::unix::io::RawFd;
@@ -340,119 +340,7 @@ libc_enum!{
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
B4000000,
}
-}
-
-impl TryFrom<libc::speed_t> for BaudRate {
- type Error = Error;
-
- fn try_from(s: libc::speed_t) -> Result<BaudRate> {
- use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
- B9600, B19200, B38400, B57600, B115200, B230400};
- #[cfg(any(target_os = "android", target_os = "linux"))]
- use libc::{B500000, B576000, B1000000, B1152000, B1500000, B2000000};
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- use libc::{B2500000, B3000000, B3500000, B4000000};
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- use libc::{B7200, B14400, B28800, B76800};
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- use libc::{B460800, B921600};
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- use libc::{B153600, B307200, B460800, B921600};
-
- match s {
- B0 => Ok(BaudRate::B0),
- B50 => Ok(BaudRate::B50),
- B75 => Ok(BaudRate::B75),
- B110 => Ok(BaudRate::B110),
- B134 => Ok(BaudRate::B134),
- B150 => Ok(BaudRate::B150),
- B200 => Ok(BaudRate::B200),
- B300 => Ok(BaudRate::B300),
- B600 => Ok(BaudRate::B600),
- B1200 => Ok(BaudRate::B1200),
- B1800 => Ok(BaudRate::B1800),
- B2400 => Ok(BaudRate::B2400),
- B4800 => Ok(BaudRate::B4800),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B7200 => Ok(BaudRate::B7200),
- B9600 => Ok(BaudRate::B9600),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B14400 => Ok(BaudRate::B14400),
- B19200 => Ok(BaudRate::B19200),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B28800 => Ok(BaudRate::B28800),
- B38400 => Ok(BaudRate::B38400),
- B57600 => Ok(BaudRate::B57600),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B76800 => Ok(BaudRate::B76800),
- B115200 => Ok(BaudRate::B115200),
- #[cfg(any(target_os = "illumos",
- target_os = "solaris"))]
- B153600 => Ok(BaudRate::B153600),
- B230400 => Ok(BaudRate::B230400),
- #[cfg(any(target_os = "illumos",
- target_os = "solaris"))]
- B307200 => Ok(BaudRate::B307200),
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- B460800 => Ok(BaudRate::B460800),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B500000 => Ok(BaudRate::B500000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B576000 => Ok(BaudRate::B576000),
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- B921600 => Ok(BaudRate::B921600),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1000000 => Ok(BaudRate::B1000000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1152000 => Ok(BaudRate::B1152000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1500000 => Ok(BaudRate::B1500000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B2000000 => Ok(BaudRate::B2000000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B2500000 => Ok(BaudRate::B2500000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3000000 => Ok(BaudRate::B3000000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3500000 => Ok(BaudRate::B3500000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B4000000 => Ok(BaudRate::B4000000),
- _ => Err(Error::from(Errno::EINVAL))
- }
- }
+ impl TryFrom<libc::speed_t>
}
#[cfg(any(target_os = "freebsd",
@@ -1118,6 +1006,7 @@ pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
#[cfg(test)]
mod test {
use super::*;
+ use std::convert::TryFrom;
#[test]
fn try_from() {