Skip to content

Commit eeb90cd

Browse files
committed
Auto merge of #129960 - pietroalbini:pa-cve-2024-43402, r=pietroalbini
[stable] Fix CVE-2024-43402 Backport the fix for CVE-2024-43402 in the upcoming 1.81.0. See GHSA-2xg3-7mm6-98jj for more information about it. This also includes #129944 as a last-minute fix to the relnotes. cc `@boxyuwu` as you are driving this release r? `@ghost`
2 parents f54dd91 + b666f82 commit eeb90cd

File tree

5 files changed

+31
-7
lines changed

5 files changed

+31
-7
lines changed

RELEASES.md

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Libraries
5050
- [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.](https://github.com/rust-lang/rust/pull/124032/) All `slice::sort*` and `slice::select_nth*` methods are expected to see significant performance improvements. See the [research project](https://github.com/Voultapher/sort-research-rs) for more details.
5151
- [Document behavior of `create_dir_all` with respect to empty paths.](https://github.com/rust-lang/rust/pull/125112/)
5252
- [Fix interleaved output in the default panic hook when multiple threads panic simultaneously.](https://github.com/rust-lang/rust/pull/127397/)
53+
- Fix `Command`'s batch files argument escaping not working when file name has trailing whitespace or periods (CVE-2024-43402).
5354

5455
<a id="1.81.0-Stabilized-APIs"></a>
5556

@@ -100,6 +101,9 @@ Compatibility Notes
100101
The reason is that these types have different roles: `std::panic::PanicHookInfo` is the argument to the [panic hook](https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html) in std context (where panics can have an arbitrary payload), while `core::panic::PanicInfo` is the argument to the [`#[panic_handler]`](https://doc.rust-lang.org/nomicon/panic-handler.html) in no_std context (where panics always carry a formatted *message*). Separating these types allows us to add more useful methods to these types, such as `std::panic::PanicHookInfo::payload_as_str()` and `core::panic::PanicInfo::message()`.
101102

102103
* The new sort implementations may panic if a type's implementation of [`Ord`](https://doc.rust-lang.org/std/cmp/trait.Ord.html) (or the given comparison function) does not implement a [total order](https://en.wikipedia.org/wiki/Total_order) as the trait requires. `Ord`'s supertraits (`PartialOrd`, `Eq`, and `PartialEq`) must also be consistent. The previous implementations would not "notice" any problem, but the new implementations have a good chance of detecting inconsistencies, throwing a panic rather than returning knowingly unsorted data.
104+
* [In very rare cases, a change in the internal evaluation order of the trait
105+
solver may result in new fatal overflow errors.](https://github.com/rust-lang/rust/pull/126128)
106+
103107

104108
<a id="1.81.0-Internal-Changes"></a>
105109

library/std/src/sys/pal/windows/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub use self::rand::hashmap_random_keys;
1414
#[macro_use]
1515
pub mod compat;
1616

17-
mod api;
17+
pub mod api;
1818

1919
pub mod alloc;
2020
pub mod args;

library/std/src/sys/pal/windows/process.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,24 @@ impl Command {
279279
None
280280
};
281281
let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?;
282-
// Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
283-
let is_batch_file = matches!(
284-
program.len().checked_sub(5).and_then(|i| program.get(i..)),
285-
Some([46, 98 | 66, 97 | 65, 116 | 84, 0] | [46, 99 | 67, 109 | 77, 100 | 68, 0])
286-
);
282+
let has_bat_extension = |program: &[u16]| {
283+
matches!(
284+
// Case insensitive "ends_with" of UTF-16 encoded ".bat" or ".cmd"
285+
program.len().checked_sub(4).and_then(|i| program.get(i..)),
286+
Some([46, 98 | 66, 97 | 65, 116 | 84] | [46, 99 | 67, 109 | 77, 100 | 68])
287+
)
288+
};
289+
let is_batch_file = if path::is_verbatim(&program) {
290+
has_bat_extension(&program[..program.len() - 1])
291+
} else {
292+
super::fill_utf16_buf(
293+
|buffer, size| unsafe {
294+
// resolve the path so we can test the final file name.
295+
c::GetFullPathNameW(program.as_ptr(), size, buffer, ptr::null_mut())
296+
},
297+
|program| has_bat_extension(program),
298+
)?
299+
};
287300
let (program, mut cmd_str) = if is_batch_file {
288301
(
289302
command_prompt()?,

library/std/src/sys/path/windows.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::ffi::{OsStr, OsString};
22
use crate::io;
33
use crate::path::{Path, PathBuf, Prefix};
44
use crate::ptr;
5+
use crate::sys::api::utf16;
56
use crate::sys::pal::{c, fill_utf16_buf, os2path, to_u16s};
67

78
#[cfg(test)]
@@ -20,6 +21,10 @@ pub fn is_verbatim_sep(b: u8) -> bool {
2021
b == b'\\'
2122
}
2223

24+
pub fn is_verbatim(path: &[u16]) -> bool {
25+
path.starts_with(utf16!(r"\\?\")) || path.starts_with(utf16!(r"\??\"))
26+
}
27+
2328
/// Returns true if `path` looks like a lone filename.
2429
pub(crate) fn is_file_name(path: &OsStr) -> bool {
2530
!path.as_encoded_bytes().iter().copied().any(is_sep_byte)

tests/ui/std/windows-bat-args.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ fn parent() {
3232
let bat2 = String::from(bat.to_str().unwrap());
3333
bat.set_file_name("windows-bat-args3.bat");
3434
let bat3 = String::from(bat.to_str().unwrap());
35-
let bat = [bat1.as_str(), bat2.as_str(), bat3.as_str()];
35+
bat.set_file_name("windows-bat-args1.bat .. ");
36+
let bat4 = String::from(bat.to_str().unwrap());
37+
let bat = [bat1.as_str(), bat2.as_str(), bat3.as_str(), bat4.as_str()];
3638

3739
check_args(&bat, &["a", "b"]).unwrap();
3840
check_args(&bat, &["c is for cat", "d is for dog"]).unwrap();

0 commit comments

Comments
 (0)