Skip to content

Commit c0a6b6d

Browse files
fix pedantic clippies (#122)
* Fix a lot of pedantic clippy warnings * Manual review and allow of possible truncations, wraps and los of sign * Fix all pointer casting clippy warnings * Make pedantic clippy the default
1 parent ca97dfd commit c0a6b6d

File tree

12 files changed

+508
-337
lines changed

12 files changed

+508
-337
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ all: clippy run-tests build-docs
33

44
.PHONY: clippy
55
clippy:
6-
cargo clippy --all --tests --all-targets --all-features -- -D warnings
6+
cargo clippy --all --tests --all-targets --all-features -- --warn clippy::pedantic -D warnings
77

88
.PHONY: configure-coverage
99
configure-coverage:

src/libproc/file_info.rs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@ use self::libc::c_void;
1010
#[cfg(target_os = "macos")]
1111
use crate::osx_libproc_bindings::proc_pidfdinfo;
1212

13-
/// Flavor of Pid FileDescriptor info for different types of File Descriptors
13+
/// Flavor of Pid `FileDescriptor` info for different types of File Descriptors
1414
pub enum PIDFDInfoFlavor {
15-
/// VNode Info
15+
/// `VNodeInfo`
1616
VNodeInfo = 1,
17-
/// VNode Path Info
17+
/// `VNodePathInfo`
1818
VNodePathInfo = 2,
19-
/// Socket info
19+
/// `SocketInfo`
2020
SocketInfo = 3,
21-
/// PSEM Info
21+
/// `PSEMInfo`
2222
PSEMInfo = 4,
23-
/// PSHM Info
23+
/// `PSHMInfo`
2424
PSHMInfo = 5,
25-
/// Pipe Info
25+
/// `PipeInfo`
2626
PipeInfo = 6,
27-
/// KQueue Info
27+
/// `KQueueInfo`
2828
KQueueInfo = 7,
29-
/// Apple Talk Info
29+
/// `AppleTalkInfo`
3030
ATalkInfo = 8,
3131
}
3232

@@ -35,22 +35,24 @@ pub struct ListFDs;
3535

3636
impl ListPIDInfo for ListFDs {
3737
type Item = ProcFDInfo;
38-
fn flavor() -> PidInfoFlavor { PidInfoFlavor::ListFDs }
38+
fn flavor() -> PidInfoFlavor {
39+
PidInfoFlavor::ListFDs
40+
}
3941
}
4042

41-
/// Struct to hold info about a Processes FileDescriptor Info
43+
/// Struct to hold info about a Processes `FileDescriptor` Info
4244
#[repr(C)]
4345
pub struct ProcFDInfo {
44-
/// File Descriptor
46+
/// `FileDescriptor`
4547
pub proc_fd: i32,
46-
/// File Descriptor type
48+
/// `FileDescriptor` type
4749
pub proc_fdtype: u32,
4850
}
4951

50-
/// Enum for different File Descriptor types
52+
/// Enum for different `FileDescriptor` types
5153
#[derive(Copy, Clone, Debug)]
5254
pub enum ProcFDType {
53-
/// AppleTalk
55+
/// `AppleTalk`
5456
ATalk = 0,
5557
/// Vnode
5658
VNode = 1,
@@ -64,8 +66,10 @@ pub enum ProcFDType {
6466
KQueue = 5,
6567
/// Pipe
6668
Pipe = 6,
67-
/// FSEvents
69+
/// `FSEvents`
6870
FSEvents = 7,
71+
/// `NetPolicy`
72+
NetPolicy = 9,
6973
/// Unknown
7074
Unknown,
7175
}
@@ -95,6 +99,10 @@ pub trait PIDFDInfo: Default {
9599

96100
/// Returns the information about file descriptors of the process that match pid passed in.
97101
///
102+
/// # Errors
103+
///
104+
/// Will return `Err`if the underlying Darwin method `proc_pidfdinfo` returns 0
105+
///
98106
/// # Examples
99107
///
100108
/// ```
@@ -153,9 +161,11 @@ pub trait PIDFDInfo: Default {
153161
#[cfg(target_os = "macos")]
154162
pub fn pidfdinfo<T: PIDFDInfo>(pid: i32, fd: i32) -> Result<T, String> {
155163
let flavor = T::flavor() as i32;
164+
// No `T` will have size greater than `i32::MAX` so no truncation
165+
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
156166
let buffer_size = mem::size_of::<T>() as i32;
157167
let mut pidinfo = T::default();
158-
let buffer_ptr = &mut pidinfo as *mut _ as *mut c_void;
168+
let buffer_ptr = std::ptr::from_mut::<T>(&mut pidinfo).cast::<c_void>();
159169
let ret: i32;
160170

161171
unsafe {
@@ -184,23 +194,26 @@ mod test {
184194
use super::pidfdinfo;
185195

186196
#[test]
197+
#[allow(clippy::cast_possible_wrap)]
187198
fn pidfdinfo_test() {
188-
use std::process;
189199
use std::net::TcpListener;
200+
use std::process;
190201
let pid = process::id() as i32;
191202

192203
let _listener = TcpListener::bind("127.0.0.1:65535");
193204

194205
let info = pidinfo::<BSDInfo>(pid, 0).expect("pidinfo() failed");
195-
let fds = listpidinfo::<ListFDs>(pid, info.pbi_nfiles as usize).expect("listpidinfo() failed");
206+
let fds =
207+
listpidinfo::<ListFDs>(pid, info.pbi_nfiles as usize).expect("listpidinfo() failed");
196208
for fd in fds {
197209
if let ProcFDType::Socket = fd.proc_fdtype.into() {
198-
let socket = pidfdinfo::<SocketFDInfo>(pid, fd.proc_fd).expect("pidfdinfo() failed");
210+
let socket =
211+
pidfdinfo::<SocketFDInfo>(pid, fd.proc_fd).expect("pidfdinfo() failed");
199212
if let SocketInfoKind::Tcp = socket.psi.soi_kind.into() {
200213
unsafe {
201214
let info = socket.psi.soi_proto.pri_tcp;
202215
assert_eq!(socket.psi.soi_protocol, libc::IPPROTO_TCP);
203-
assert_eq!(info.tcpsi_ini.insi_lport as u32, 65535);
216+
assert_eq!(info.tcpsi_ini.insi_lport, 65535);
204217
}
205218
}
206219
}

src/libproc/helpers.rs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fs::File;
44
#[cfg(any(target_os = "linux", target_os = "redox", target_os = "android"))]
55
use std::io::{BufRead, BufReader};
66

7-
/// Helper function to get errno and return a String with the passed in return_code, the error
7+
/// Helper function to get errno and return a String with the passed in `return_code`, the error
88
/// number and a possible message
99
pub fn get_errno_with_message(return_code: i32) -> String {
1010
let e = errno();
@@ -19,26 +19,29 @@ pub fn check_errno(ret: i32, buf: &mut Vec<u8>) -> Result<String, String> {
1919
if ret <= 0 {
2020
Err(get_errno_with_message(ret))
2121
} else {
22+
// `ret` mucg be greater than 0 here so no sign-loss
23+
#[allow(clippy::cast_sign_loss)]
2224
unsafe {
2325
buf.set_len(ret as usize);
2426
}
2527

26-
match String::from_utf8(buf.to_vec()) {
28+
match String::from_utf8(buf.clone()) {
2729
Ok(return_value) => Ok(return_value),
28-
Err(e) => Err(format!("Invalid UTF-8 sequence: {e}"))
30+
Err(e) => Err(format!("Invalid UTF-8 sequence: {e}")),
2931
}
3032
}
3133
}
3234

3335
#[cfg(any(target_os = "linux", target_os = "redox", target_os = "android"))]
3436
/// A helper function for finding named fields in specific /proc FS files for processes
3537
/// This will be more useful when implementing more linux functions
36-
pub fn procfile_field(filename: &str, field_name: &str) -> Result<String, String> {
38+
pub(crate) fn procfile_field(filename: &str, field_name: &str) -> Result<String, String> {
3739
const SEPARATOR: &str = ":";
3840
let line_header = format!("{field_name}{SEPARATOR}");
3941

4042
// Open the file in read-only mode (ignoring errors).
41-
let file = File::open(filename).map_err(|_| format!("Could not open /proc file '{filename}'"))?;
43+
let file =
44+
File::open(filename).map_err(|_| format!("Could not open /proc file '{filename}'"))?;
4245
let reader = BufReader::new(file);
4346

4447
// Read the file line by line using the lines() iterator from std::io::BufRead.
@@ -50,7 +53,9 @@ pub fn procfile_field(filename: &str, field_name: &str) -> Result<String, String
5053
}
5154
}
5255

53-
Err(format!("Could not find the field named '{field_name}' in the /proc FS file name '{filename}'"))
56+
Err(format!(
57+
"Could not find the field named '{field_name}' in the /proc FS file name '{filename}'"
58+
))
5459
}
5560

5661
#[cfg(any(target_os = "linux", target_os = "redox", target_os = "android"))]
@@ -59,42 +64,43 @@ pub fn procfile_field(filename: &str, field_name: &str) -> Result<String, String
5964
pub fn parse_memory_string(line: &str) -> Result<u64, String> {
6065
let parts: Vec<&str> = line.trim().split(' ').collect();
6166
if parts.is_empty() {
62-
return Err(format!("Could not parse Memory String: {line}"))
67+
return Err(format!("Could not parse Memory String: {line}"));
6368
}
6469
let multiplier: u64 = if parts.len() == 2 {
65-
match parts[1] {
66-
"MB" => 1024 * 1024,
67-
"kB" => 1024,
68-
"B" => 1,
69-
_ => return Err(format!("Could not parse units of Memory String: {line}"))
70+
match parts.get(1) {
71+
Some(&"MB") => 1024 * 1024,
72+
Some(&"kB") => 1024,
73+
Some(&"B") => 1,
74+
_ => return Err(format!("Could not parse units of Memory String: {line}")),
7075
}
7176
} else {
7277
1
7378
};
7479

75-
let value:u64 = parts[0].parse()
80+
let value: u64 = parts[0]
81+
.parse()
7682
.map_err(|_| "Could not parse value as integer")?;
7783

7884
Ok(value * multiplier)
7985
}
8086

8187
#[cfg(test)]
8288
mod test {
83-
use crate::errno::{set_errno, Errno};
8489
use super::check_errno;
90+
use crate::errno::{set_errno, Errno};
8591

8692
#[cfg(any(target_os = "linux", target_os = "redox", target_os = "android"))]
8793
mod linux {
8894
use crate::libproc::helpers::parse_memory_string;
8995

9096
#[test]
9197
fn test_valid_memory_string() {
92-
assert_eq!(parse_memory_string("220844 kB"), Ok(226144256));
98+
assert_eq!(parse_memory_string("220844 kB"), Ok(226_144_256));
9399
}
94100

95101
#[test]
96102
fn test_valid_memory_string_spaces() {
97-
assert_eq!(parse_memory_string(" 220844 kB "), Ok(226144256));
103+
assert_eq!(parse_memory_string(" 220844 kB "), Ok(226_144_256));
98104
}
99105

100106
#[test]
@@ -109,17 +115,20 @@ mod test {
109115

110116
#[test]
111117
fn test_invalid_memory_string_empty() {
112-
assert!(parse_memory_string("gobble dee gook").is_err())
118+
assert!(parse_memory_string("gobble dee gook").is_err());
113119
}
114120
}
115121

116122
#[test]
117123
fn invalid_utf8() {
118-
let mut buf: Vec<u8> = vec!(255, 0, 0);
124+
let mut buf: Vec<u8> = vec![255, 0, 0];
119125

120-
// Test
126+
// Test - small test buffer so no problem truncating
127+
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
121128
if let Err(msg) = check_errno(buf.len() as i32, &mut buf) {
122-
assert!(msg.contains("Invalid UTF-8 sequence: invalid utf-8 sequence of 1 bytes from index 0"))
129+
assert!(msg.contains(
130+
"Invalid UTF-8 sequence: invalid utf-8 sequence of 1 bytes from index 0"
131+
));
123132
}
124133
}
125134

@@ -128,15 +137,16 @@ mod test {
128137
let message = "custom message";
129138
let mut buf: Vec<u8> = Vec::from(message.as_bytes());
130139

131-
// Test
140+
// Test - small test buffer so no problem truncating
141+
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
132142
if let Ok(msg) = check_errno(buf.len() as i32, &mut buf) {
133143
assert!(msg.contains(message));
134144
}
135145
}
136146

137147
#[test]
138148
fn negative_ret() {
139-
let mut buf: Vec<u8> = vec!();
149+
let mut buf: Vec<u8> = vec![];
140150
set_errno(Errno(-1));
141151

142152
// Test
@@ -147,12 +157,12 @@ mod test {
147157

148158
#[test]
149159
fn zero_ret() {
150-
let mut buf: Vec<u8> = vec!();
160+
let mut buf: Vec<u8> = vec![];
151161
set_errno(Errno(2));
152162

153163
// Test
154164
if let Err(mes) = check_errno(0, &mut buf) {
155-
assert!(mes.contains("return code = 0, errno = 2"))
165+
assert!(mes.contains("return code = 0, errno = 2"));
156166
}
157167
}
158168
}

0 commit comments

Comments
 (0)