Skip to content

Commit 27011d5

Browse files
committed
Auto merge of rust-lang#123682 - pietroalbini:pa-cve-2024-24576-beta, r=pietroalbini
[beta] Backport fix of CVE-2024-24576 r? `@ghost` See https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html
2 parents 9eff510 + fa1e080 commit 27011d5

File tree

9 files changed

+456
-14
lines changed

9 files changed

+456
-14
lines changed

RELEASES.md

+134
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,137 @@
1+
Version 1.77.2 (2024-04-09)
2+
===========================
3+
4+
<a id="1.77.2"></a>
5+
6+
- [CVE-2024-24576: fix escaping of Windows batch file arguments in `std::process::Command`](https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html)
7+
8+
Version 1.77.1 (2024-03-28)
9+
===========================
10+
11+
<a id="1.77.1"></a>
12+
13+
- [Revert stripping debuginfo by default for Windows](https://github.com/rust-lang/cargo/pull/13654)
14+
This fixes a regression in 1.77 by reverting to the previous default.
15+
Platforms other than Windows are not affected.
16+
- Internal: [Fix heading anchor rendering in doc pages](https://github.com/rust-lang/rust/pull/122693)
17+
18+
Version 1.77.0 (2024-03-21)
19+
==========================
20+
21+
<a id="1.77.0-Language"></a>
22+
23+
Language
24+
--------
25+
26+
- [Reveal opaque types within the defining body for exhaustiveness checking.](https://github.com/rust-lang/rust/pull/116821/)
27+
- [Stabilize C-string literals.](https://github.com/rust-lang/rust/pull/117472/)
28+
- [Stabilize THIR unsafeck.](https://github.com/rust-lang/rust/pull/117673/)
29+
- [Add lint `static_mut_refs` to warn on references to mutable statics.](https://github.com/rust-lang/rust/pull/117556/)
30+
- [Support async recursive calls (as long as they have indirection).](https://github.com/rust-lang/rust/pull/117703/)
31+
- [Undeprecate lint `unstable_features` and make use of it in the compiler.](https://github.com/rust-lang/rust/pull/118639/)
32+
- [Make inductive cycles in coherence ambiguous always.](https://github.com/rust-lang/rust/pull/118649/)
33+
- [Get rid of type-driven traversal in const-eval interning](https://github.com/rust-lang/rust/pull/119044/),
34+
only as a [future compatiblity lint](https://github.com/rust-lang/rust/pull/122204) for now.
35+
- [Deny braced macro invocations in let-else.](https://github.com/rust-lang/rust/pull/119062/)
36+
37+
<a id="1.77.0-Compiler"></a>
38+
39+
Compiler
40+
--------
41+
42+
- [Include lint `soft_unstable` in future breakage reports.](https://github.com/rust-lang/rust/pull/116274/)
43+
- [Make `i128` and `u128` 16-byte aligned on x86-based targets.](https://github.com/rust-lang/rust/pull/116672/)
44+
- [Use `--verbose` in diagnostic output.](https://github.com/rust-lang/rust/pull/119129/)
45+
- [Improve spacing between printed tokens.](https://github.com/rust-lang/rust/pull/120227/)
46+
- [Merge the `unused_tuple_struct_fields` lint into `dead_code`.](https://github.com/rust-lang/rust/pull/118297/)
47+
- [Error on incorrect implied bounds in well-formedness check](https://github.com/rust-lang/rust/pull/118553/),
48+
with a temporary exception for Bevy.
49+
- [Fix coverage instrumentation/reports for non-ASCII source code.](https://github.com/rust-lang/rust/pull/119033/)
50+
- [Fix `fn`/`const` items implied bounds and well-formedness check.](https://github.com/rust-lang/rust/pull/120019/)
51+
- [Promote `riscv32{im|imafc}-unknown-none-elf` targets to tier 2.](https://github.com/rust-lang/rust/pull/118704/)
52+
- Add several new tier 3 targets:
53+
- [`aarch64-unknown-illumos`](https://github.com/rust-lang/rust/pull/112936/)
54+
- [`hexagon-unknown-none-elf`](https://github.com/rust-lang/rust/pull/117601/)
55+
- [`riscv32imafc-esp-espidf`](https://github.com/rust-lang/rust/pull/119738/)
56+
- [`riscv32im-risc0-zkvm-elf`](https://github.com/rust-lang/rust/pull/117958/)
57+
58+
Refer to Rust's [platform support page][platform-support-doc]
59+
for more information on Rust's tiered platform support.
60+
61+
<a id="1.77.0-Libraries"></a>
62+
63+
Libraries
64+
---------
65+
66+
- [Implement `From<&[T; N]>` for `Cow<[T]>`.](https://github.com/rust-lang/rust/pull/113489/)
67+
- [Remove special-case handling of `vec.split_off(0)`.](https://github.com/rust-lang/rust/pull/119917/)
68+
69+
<a id="1.77.0-Stabilized-APIs"></a>
70+
71+
Stabilized APIs
72+
---------------
73+
74+
- [`array::each_ref`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_ref)
75+
- [`array::each_mut`](https://doc.rust-lang.org/stable/std/primitive.array.html#method.each_mut)
76+
- [`core::net`](https://doc.rust-lang.org/stable/core/net/index.html)
77+
- [`f32::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.round_ties_even)
78+
- [`f64::round_ties_even`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.round_ties_even)
79+
- [`mem::offset_of!`](https://doc.rust-lang.org/stable/std/mem/macro.offset_of.html)
80+
- [`slice::first_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first_chunk)
81+
- [`slice::first_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first_chunk_mut)
82+
- [`slice::split_first_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first_chunk)
83+
- [`slice::split_first_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first_chunk_mut)
84+
- [`slice::last_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last_chunk)
85+
- [`slice::last_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last_chunk_mut)
86+
- [`slice::split_last_chunk`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last_chunk)
87+
- [`slice::split_last_chunk_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last_chunk_mut)
88+
- [`slice::chunk_by`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.chunk_by)
89+
- [`slice::chunk_by_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.chunk_by_mut)
90+
- [`Bound::map`](https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.map)
91+
- [`File::create_new`](https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.create_new)
92+
- [`Mutex::clear_poison`](https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html#method.clear_poison)
93+
- [`RwLock::clear_poison`](https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html#method.clear_poison)
94+
95+
<a id="1.77.0-Cargo"></a>
96+
97+
Cargo
98+
-----
99+
100+
- [Extend the build directive syntax with `cargo::`.](https://github.com/rust-lang/cargo/pull/12201/)
101+
- [Stabilize metadata `id` format as `PackageIDSpec`.](https://github.com/rust-lang/cargo/pull/12914/)
102+
- [Pull out as `cargo-util-schemas` as a crate.](https://github.com/rust-lang/cargo/pull/13178/)
103+
- [Strip all debuginfo when debuginfo is not requested.](https://github.com/rust-lang/cargo/pull/13257/)
104+
- [Inherit jobserver from env for all kinds of runners.](https://github.com/rust-lang/cargo/pull/12776/)
105+
- [Deprecate rustc plugin support in cargo.](https://github.com/rust-lang/cargo/pull/13248/)
106+
107+
<a id="1.77.0-Rustdoc"></a>
108+
109+
Rustdoc
110+
-----
111+
112+
- [Allows links in markdown headings.](https://github.com/rust-lang/rust/pull/117662/)
113+
- [Search for tuples and unit by type with `()`.](https://github.com/rust-lang/rust/pull/118194/)
114+
- [Clean up the source sidebar's hide button.](https://github.com/rust-lang/rust/pull/119066/)
115+
- [Prevent JS injection from `localStorage`.](https://github.com/rust-lang/rust/pull/120250/)
116+
117+
<a id="1.77.0-Misc"></a>
118+
119+
Misc
120+
----
121+
122+
- [Recommend version-sorting for all sorting in style guide.](https://github.com/rust-lang/rust/pull/115046/)
123+
124+
<a id="1.77.0-Internal-Changes"></a>
125+
126+
Internal Changes
127+
----------------
128+
129+
These changes do not affect any public interfaces of Rust, but they represent
130+
significant improvements to the performance or internals of rustc and related
131+
tools.
132+
133+
- [Add more weirdness to `weird-exprs.rs`.](https://github.com/rust-lang/rust/pull/119028/)
134+
1135
Version 1.76.0 (2024-02-08)
2136
==========================
3137

library/std/src/os/windows/process.rs

+54-2
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,60 @@ pub trait CommandExt: Sealed {
199199

200200
/// Append literal text to the command line without any quoting or escaping.
201201
///
202-
/// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
203-
/// `CommandLineToArgvW` escaping rules.
202+
/// This is useful for passing arguments to applications which doesn't follow
203+
/// the standard C run-time escaping rules, such as `cmd.exe /c`.
204+
///
205+
/// # Bat files
206+
///
207+
/// Note the `cmd /c` command line has slightly different escaping rules then bat files
208+
/// themselves. If possible, it may be better to write complex arguments to a temporary
209+
/// .bat file, with appropriate escaping, and simply run that using:
210+
///
211+
/// ```no_run
212+
/// # use std::process::Command;
213+
/// # let temp_bat_file = "";
214+
/// # #[allow(unused)]
215+
/// let output = Command::new("cmd").args(["/c", &format!("\"{temp_bat_file}\"")]).output();
216+
/// ```
217+
///
218+
/// # Example
219+
///
220+
/// Run a bat script using both trusted and untrusted arguments.
221+
///
222+
/// ```no_run
223+
/// #[cfg(windows)]
224+
/// // `my_script_path` is a path to known bat file.
225+
/// // `user_name` is an untrusted name given by the user.
226+
/// fn run_script(
227+
/// my_script_path: &str,
228+
/// user_name: &str,
229+
/// ) -> Result<std::process::Output, std::io::Error> {
230+
/// use std::io::{Error, ErrorKind};
231+
/// use std::os::windows::process::CommandExt;
232+
/// use std::process::Command;
233+
///
234+
/// // Create the command line, making sure to quote the script path.
235+
/// // This assumes the fixed arguments have been tested to work with the script we're using.
236+
/// let mut cmd_args = format!(r#""{my_script_path}" "--features=[a,b,c]""#);
237+
///
238+
/// // Make sure the user name is safe. In particular we need to be
239+
/// // cautious of ascii symbols that cmd may interpret specially.
240+
/// // Here we only allow alphanumeric characters.
241+
/// if !user_name.chars().all(|c| c.is_alphanumeric()) {
242+
/// return Err(Error::new(ErrorKind::InvalidInput, "invalid user name"));
243+
/// }
244+
/// // now we've checked the user name, let's add that too.
245+
/// cmd_args.push(' ');
246+
/// cmd_args.push_str(&format!("--user {user_name}"));
247+
///
248+
/// // call cmd.exe and return the output
249+
/// Command::new("cmd.exe")
250+
/// .arg("/c")
251+
/// // surround the entire command in an extra pair of quotes, as required by cmd.exe.
252+
/// .raw_arg(&format!("\"{cmd_args}\""))
253+
/// .output()
254+
/// }
255+
/// ````
204256
#[stable(feature = "windows_process_extensions_raw_arg", since = "1.62.0")]
205257
fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command;
206258

library/std/src/process.rs

+79
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,47 @@
8888
//! assert_eq!(b"test", output.stdout.as_slice());
8989
//! ```
9090
//!
91+
//! # Windows argument splitting
92+
//!
93+
//! On Unix systems arguments are passed to a new process as an array of strings
94+
//! but on Windows arguments are passed as a single commandline string and it's
95+
//! up to the child process to parse it into an array. Therefore the parent and
96+
//! child processes must agree on how the commandline string is encoded.
97+
//!
98+
//! Most programs use the standard C run-time `argv`, which in practice results
99+
//! in consistent argument handling. However some programs have their own way of
100+
//! parsing the commandline string. In these cases using [`arg`] or [`args`] may
101+
//! result in the child process seeing a different array of arguments then the
102+
//! parent process intended.
103+
//!
104+
//! Two ways of mitigating this are:
105+
//!
106+
//! * Validate untrusted input so that only a safe subset is allowed.
107+
//! * Use [`raw_arg`] to build a custom commandline. This bypasses the escaping
108+
//! rules used by [`arg`] so should be used with due caution.
109+
//!
110+
//! `cmd.exe` and `.bat` use non-standard argument parsing and are especially
111+
//! vulnerable to malicious input as they may be used to run arbitrary shell
112+
//! commands. Untrusted arguments should be restricted as much as possible.
113+
//! For examples on handling this see [`raw_arg`].
114+
//!
115+
//! ### Bat file special handling
116+
//!
117+
//! On Windows, `Command` uses the Windows API function [`CreateProcessW`] to
118+
//! spawn new processes. An undocumented feature of this function is that,
119+
//! when given a `.bat` file as the application to run, it will automatically
120+
//! convert that into running `cmd.exe /c` with the bat file as the next argument.
121+
//!
122+
//! For historical reasons Rust currently preserves this behaviour when using
123+
//! [`Command::new`], and escapes the arguments according to `cmd.exe` rules.
124+
//! Due to the complexity of `cmd.exe` argument handling, it might not be
125+
//! possible to safely escape some special chars, and using them will result
126+
//! in an error being returned at process spawn. The set of unescapeable
127+
//! special chars might change between releases.
128+
//!
129+
//! Also note that running `.bat` scripts in this way may be removed in the
130+
//! future and so should not be relied upon.
131+
//!
91132
//! [`spawn`]: Command::spawn
92133
//! [`output`]: Command::output
93134
//!
@@ -97,6 +138,12 @@
97138
//!
98139
//! [`Write`]: io::Write
99140
//! [`Read`]: io::Read
141+
//!
142+
//! [`arg`]: Command::arg
143+
//! [`args`]: Command::args
144+
//! [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
145+
//!
146+
//! [`CreateProcessW`]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
100147
101148
#![stable(feature = "process", since = "1.0.0")]
102149
#![deny(unsafe_op_in_unsafe_fn)]
@@ -611,6 +658,22 @@ impl Command {
611658
/// escaped characters, word splitting, glob patterns, variable substitution, etc.
612659
/// have no effect.
613660
///
661+
/// <div class="warning">
662+
///
663+
/// On Windows use caution with untrusted inputs. Most applications use the
664+
/// standard convention for decoding arguments passed to them. These are safe to use with `arg`.
665+
/// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
666+
/// and are therefore vulnerable to malicious input.
667+
/// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
668+
///
669+
/// See [Windows argument splitting][windows-args] for more details
670+
/// or [`raw_arg`] for manually implementing non-standard argument encoding.
671+
///
672+
/// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
673+
/// [windows-args]: crate::process#windows-argument-splitting
674+
///
675+
/// </div>
676+
///
614677
/// # Examples
615678
///
616679
/// Basic usage:
@@ -641,6 +704,22 @@ impl Command {
641704
/// escaped characters, word splitting, glob patterns, variable substitution, etc.
642705
/// have no effect.
643706
///
707+
/// <div class="warning">
708+
///
709+
/// On Windows use caution with untrusted inputs. Most applications use the
710+
/// standard convention for decoding arguments passed to them. These are safe to use with `args`.
711+
/// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
712+
/// and are therefore vulnerable to malicious input.
713+
/// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
714+
///
715+
/// See [Windows argument splitting][windows-args] for more details
716+
/// or [`raw_arg`] for manually implementing non-standard argument encoding.
717+
///
718+
/// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
719+
/// [windows-args]: crate::process#windows-argument-splitting
720+
///
721+
/// </div>
722+
///
644723
/// # Examples
645724
///
646725
/// Basic usage:

0 commit comments

Comments
 (0)