about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/backtrace.rs6
-rw-r--r--library/std/src/process/tests.rs29
-rw-r--r--library/std/src/sync/once.rs7
-rw-r--r--library/std/src/sys/solid/fs.rs28
-rw-r--r--library/std/src/sys/windows/process.rs16
-rw-r--r--library/std/src/sys/windows/process/tests.rs4
6 files changed, 83 insertions, 7 deletions
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 0b86b4f30b9..94e6070c0f7 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -99,7 +99,7 @@ use crate::cell::UnsafeCell;
 use crate::env;
 use crate::ffi::c_void;
 use crate::fmt;
-use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
+use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
 use crate::sync::Once;
 use crate::sys_common::backtrace::{lock, output_filename};
 use crate::vec::Vec;
@@ -256,7 +256,7 @@ impl Backtrace {
         // backtrace captures speedy, because otherwise reading environment
         // variables every time can be somewhat slow.
         static ENABLED: AtomicUsize = AtomicUsize::new(0);
-        match ENABLED.load(SeqCst) {
+        match ENABLED.load(Relaxed) {
             0 => {}
             1 => return false,
             _ => return true,
@@ -268,7 +268,7 @@ impl Backtrace {
                 Err(_) => false,
             },
         };
-        ENABLED.store(enabled as usize + 1, SeqCst);
+        ENABLED.store(enabled as usize + 1, Relaxed);
         enabled
     }
 
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 67b747e4107..e5cdc473706 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -4,6 +4,10 @@ use super::{Command, Output, Stdio};
 use crate::io::ErrorKind;
 use crate::str;
 
+fn known_command() -> Command {
+    if cfg!(windows) { Command::new("help") } else { Command::new("echo") }
+}
+
 #[cfg(target_os = "android")]
 fn shell_cmd() -> Command {
     Command::new("/system/bin/sh")
@@ -305,7 +309,7 @@ fn test_interior_nul_in_progname_is_error() {
 
 #[test]
 fn test_interior_nul_in_arg_is_error() {
-    match Command::new("rustc").arg("has-some-\0\0s-inside").spawn() {
+    match known_command().arg("has-some-\0\0s-inside").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
         Ok(_) => panic!(),
     }
@@ -313,7 +317,7 @@ fn test_interior_nul_in_arg_is_error() {
 
 #[test]
 fn test_interior_nul_in_args_is_error() {
-    match Command::new("rustc").args(&["has-some-\0\0s-inside"]).spawn() {
+    match known_command().args(&["has-some-\0\0s-inside"]).spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
         Ok(_) => panic!(),
     }
@@ -321,7 +325,7 @@ fn test_interior_nul_in_args_is_error() {
 
 #[test]
 fn test_interior_nul_in_current_dir_is_error() {
-    match Command::new("rustc").current_dir("has-some-\0\0s-inside").spawn() {
+    match known_command().current_dir("has-some-\0\0s-inside").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
         Ok(_) => panic!(),
     }
@@ -416,3 +420,22 @@ fn env_empty() {
     let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn();
     assert!(p.is_ok());
 }
+
+// See issue #91991
+#[test]
+#[cfg(windows)]
+fn run_bat_script() {
+    let tempdir = crate::sys_common::io::test::tmpdir();
+    let script_path = tempdir.join("hello.cmd");
+
+    crate::fs::write(&script_path, "@echo Hello, %~1!").unwrap();
+    let output = Command::new(&script_path)
+        .arg("fellow Rustaceans")
+        .stdout(crate::process::Stdio::piped())
+        .spawn()
+        .unwrap()
+        .wait_with_output()
+        .unwrap();
+    assert!(output.status.success());
+    assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "Hello, fellow Rustaceans!");
+}
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 1710c005393..f76d0759561 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -90,6 +90,7 @@ mod tests;
 use crate::cell::Cell;
 use crate::fmt;
 use crate::marker;
+use crate::panic::{RefUnwindSafe, UnwindSafe};
 use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
 use crate::thread::{self, Thread};
 
@@ -123,6 +124,12 @@ unsafe impl Sync for Once {}
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl Send for Once {}
 
+#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")]
+impl UnwindSafe for Once {}
+
+#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")]
+impl RefUnwindSafe for Once {}
+
 /// State yielded to [`Once::call_once_force()`]’s closure parameter. The state
 /// can be used to query the poison status of the [`Once`].
 #[stable(feature = "once_poison", since = "1.51.0")]
diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs
index abc60b56fbb..8a0eeff0c4d 100644
--- a/library/std/src/sys/solid/fs.rs
+++ b/library/std/src/sys/solid/fs.rs
@@ -2,7 +2,7 @@ use super::{abi, error};
 use crate::{
     ffi::{CStr, CString, OsStr, OsString},
     fmt,
-    io::{self, IoSlice, IoSliceMut, SeekFrom},
+    io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom},
     mem::MaybeUninit,
     os::raw::{c_int, c_short},
     os::solid::ffi::OsStrExt,
@@ -339,6 +339,32 @@ impl File {
         }
     }
 
+    pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> {
+        unsafe {
+            let len = buf.remaining();
+            let mut out_num_bytes = MaybeUninit::uninit();
+            error::SolidError::err_if_negative(abi::SOLID_FS_Read(
+                self.fd.raw(),
+                buf.unfilled_mut().as_mut_ptr() as *mut u8,
+                len,
+                out_num_bytes.as_mut_ptr(),
+            ))
+            .map_err(|e| e.as_io_error())?;
+
+            // Safety: `out_num_bytes` is filled by the successful call to
+            // `SOLID_FS_Read`
+            let num_bytes_read = out_num_bytes.assume_init();
+
+            // Safety: `num_bytes_read` bytes were written to the unfilled
+            // portion of the buffer
+            buf.assume_init(num_bytes_read);
+
+            buf.add_filled(num_bytes_read);
+
+            Ok(())
+        }
+    }
+
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         crate::io::default_read_vectored(|buf| self.read(buf), bufs)
     }
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 66b210ce1bf..e84dfbce4a7 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -704,6 +704,19 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
     // Encode the command and arguments in a command line string such
     // that the spawned process may recover them using CommandLineToArgvW.
     let mut cmd: Vec<u16> = Vec::new();
+
+    // CreateFileW has special handling for .bat and .cmd files, which means we
+    // need to add an extra pair of quotes surrounding the whole command line
+    // so they are properly passed on to the script.
+    // See issue #91991.
+    let is_batch_file = Path::new(prog)
+        .extension()
+        .map(|ext| ext.eq_ignore_ascii_case("cmd") || ext.eq_ignore_ascii_case("bat"))
+        .unwrap_or(false);
+    if is_batch_file {
+        cmd.push(b'"' as u16);
+    }
+
     // Always quote the program name so CreateProcess doesn't interpret args as
     // part of the name if the binary wasn't found first time.
     append_arg(&mut cmd, prog, Quote::Always)?;
@@ -715,6 +728,9 @@ fn make_command_line(prog: &OsStr, args: &[Arg], force_quotes: bool) -> io::Resu
         };
         append_arg(&mut cmd, arg, quote)?;
     }
+    if is_batch_file {
+        cmd.push(b'"' as u16);
+    }
     return Ok(cmd);
 
     fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr, quote: Quote) -> io::Result<()> {
diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs
index 6c862edc237..6159a679c0e 100644
--- a/library/std/src/sys/windows/process/tests.rs
+++ b/library/std/src/sys/windows/process/tests.rs
@@ -160,6 +160,8 @@ fn windows_exe_resolver() {
         io::ErrorKind::InvalidInput
     );
 
+    /* FIXME: fix and re-enable these tests before making changes to the resolver.
+
     /*
     Some of the following tests may need to be changed if you are deliberately
     changing the behaviour of `resolve_exe`.
@@ -179,4 +181,6 @@ fn windows_exe_resolver() {
     // The application's directory is also searched.
     let current_exe = env::current_exe().unwrap();
     assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), None).is_ok());
+
+    */
 }