about summary refs log tree commit diff
path: root/library/std/src/sys/unix
diff options
context:
space:
mode:
authorShE3py <52315535+she3py@users.noreply.github.com>2023-08-18 16:04:53 +0200
committerShE3py <52315535+she3py@users.noreply.github.com>2023-08-18 16:04:53 +0200
commit83c713bff022acabc4dab30510f35122e29d0f53 (patch)
treef8d247c25f4e8e1b495ec527355462fda18c79e3 /library/std/src/sys/unix
parent0f7f6b70617fbcda9f73755fa9b560bfb0a588eb (diff)
downloadrust-83c713bff022acabc4dab30510f35122e29d0f53.tar.gz
rust-83c713bff022acabc4dab30510f35122e29d0f53.zip
Fix UB in `std::sys::os::getenv()`
Diffstat (limited to 'library/std/src/sys/unix')
-rw-r--r--library/std/src/sys/unix/os.rs21
1 files changed, 13 insertions, 8 deletions
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 215f63d04f7..57e1a36dace 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -594,16 +594,21 @@ pub fn env() -> Env {
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     // environment variables with a nul byte can't be set, so their value is
     // always None as well
-    let s = run_with_cstr(k.as_bytes(), |k| {
+    run_with_cstr(k.as_bytes(), |k| {
         let _guard = env_read_lock();
-        Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
     })
-    .ok()?;
-    if s.is_null() {
-        None
-    } else {
-        Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
-    }
+    .ok()
+    .flatten()
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {