Repository: GuillaumeGomez/sysinfo (language: rust)

Issue:
cmdline file without NULL will cause Sysinfo to be unable to get the command line string
**Describe the bug**
Fill the content of the entire cmdline through some dirty methods and do not keep the end of the NULL character. At this time, Sysinfo will not be able to read the command line of the corresponding process

sysinfo 0.30.13 on linux

**To Reproduce**
This can only be reproduced if the output of env | wc -c is greater than 4096:

run `git clone https://github.com/unknowndevQwQ/killmyargv && cargo test`
The expectation is that there should be a long string in left, but what actually happens is that no string is obtained. And procps-ng can read cmdline normally in this case



Discussion / hints:

Fix patch:
diff --git a/src/unix/linux/process.rs b/src/unix/linux/process.rs
index 310802b98..cb62c2276 100644
--- a/src/unix/linux/process.rs
+++ b/src/unix/linux/process.rs
@@ -827,6 +827,24 @@ fn trim_ascii(mut bytes: &[u8]) -> &[u8] {
     bytes
 }
 
+fn split_content(mut data: &[u8]) -> Vec<OsString> {
+    let mut out = Vec::with_capacity(10);
+    while let Some(pos) = data.iter().position(|c| *c == 0) {
+        let s = trim_ascii(&data[..pos]);
+        if !s.is_empty() {
+            out.push(OsStr::from_bytes(s).to_os_string());
+        }
+        data = &data[pos + 1..];
+    }
+    if !data.is_empty() {
+        let s = trim_ascii(data);
+        if !s.is_empty() {
+            out.push(OsStr::from_bytes(s).to_os_string());
+        }
+    }
+    out
+}
+
 fn copy_from_file(entry: &Path) -> Vec<OsString> {
     match File::open(entry) {
         Ok(mut f) => {
@@ -836,16 +854,7 @@ fn copy_from_file(entry: &Path) -> Vec<OsString> {
                 sysinfo_debug!("Failed to read file in `copy_from_file`: {:?}", _e);
                 Vec::new()
             } else {
-                let mut out = Vec::with_capacity(10);
-                let mut data = data.as_slice();
-                while let Some(pos) = data.iter().position(|c| *c == 0) {
-                    let s = trim_ascii(&data[..pos]);
-                    if !s.is_empty() {
-                        out.push(OsStr::from_bytes(s).to_os_string());
-                    }
-                    data = &data[pos + 1..];
-                }
-                out
+                split_content(&data)
             }
         }
         Err(_e) => {
@@ -967,3 +976,24 @@ impl Drop for FileCounter {
         remaining_files().fetch_add(1, Ordering::Relaxed);
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::split_content;
+    use std::ffi::OsString;
+
+    // This test ensures that all the parts of the data are split.
+    #[test]
+    fn test_copy_file() {
+        assert_eq!(split_content(b"hello\0"), vec![OsString::from("hello")]);
+        assert_eq!(split_content(b"hello"), vec![OsString::from("hello")]);
+        assert_eq!(
+            split_content(b"hello\0b"),
+            vec![OsString::from("hello"), "b".into()]
+        );
+        assert_eq!(
+            split_content(b"hello\0\0\0\0b"),
+            vec![OsString::from("hello"), "b".into()]
+        );
+    }
+}


Test patch: