diff --git a/Cargo.lock b/Cargo.lock index 3dba4f935e595..1a0eb7d0bd411 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "addr2line" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" +checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" dependencies = [ "compiler_builtins", "gimli", @@ -132,13 +132,13 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.53" +version = "0.3.55" dependencies = [ "addr2line", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.21.1", + "object", "rustc-demangle", ] @@ -1292,9 +1292,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", @@ -2181,21 +2181,15 @@ dependencies = [ [[package]] name = "object" -version = "0.20.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" dependencies = [ "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] -[[package]] -name = "object" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693" - [[package]] name = "once_cell" version = "1.4.1" @@ -4668,7 +4662,7 @@ dependencies = [ "hermit-abi", "libc", "miniz_oxide", - "object 0.20.0", + "object", "panic_abort", "panic_unwind", "profiler_builtins", @@ -5262,7 +5256,7 @@ dependencies = [ "chrono", "lazy_static", "matchers", - "parking_lot 0.9.0", + "parking_lot 0.11.0", "regex", "serde", "serde_json", diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index c544761255534..e49e456792b0d 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1286,6 +1286,7 @@ pub fn init_env_logger(env: &str) { } let filter = tracing_subscriber::EnvFilter::from_env(env); let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) .with_indent_lines(true) .with_ansi(true) .with_targets(true) diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index f117ce1f80544..dd2627f7bc15c 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -127,14 +127,20 @@ impl NonCamelCaseTypes { if !is_camel_case(name) { cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| { let msg = format!("{} `{}` should have an upper camel case name", sort, name); - lint.build(&msg) - .span_suggestion( + let mut err = lint.build(&msg); + let cc = to_camel_case(name); + // We cannot provide meaningful suggestions + // if the characters are in the category of "Lowercase Letter". + if name.to_string() != cc { + err.span_suggestion( ident.span, "convert the identifier to upper camel case", to_camel_case(name), Applicability::MaybeIncorrect, - ) - .emit() + ); + } + + err.emit(); }) } } @@ -263,17 +269,21 @@ impl NonSnakeCase { let sc = NonSnakeCase::to_snake_case(name); let msg = format!("{} `{}` should have a snake case name", sort, name); let mut err = lint.build(&msg); - // We have a valid span in almost all cases, but we don't have one when linting a crate - // name provided via the command line. - if !ident.span.is_dummy() { - err.span_suggestion( - ident.span, - "convert the identifier to snake case", - sc, - Applicability::MaybeIncorrect, - ); - } else { - err.help(&format!("convert the identifier to snake case: `{}`", sc)); + // We cannot provide meaningful suggestions + // if the characters are in the category of "Uppercase Letter". + if name.to_string() != sc { + // We have a valid span in almost all cases, but we don't have one when linting a crate + // name provided via the command line. + if !ident.span.is_dummy() { + err.span_suggestion( + ident.span, + "convert the identifier to snake case", + sc, + Applicability::MaybeIncorrect, + ); + } else { + err.help(&format!("convert the identifier to snake case: `{}`", sc)); + } } err.emit(); @@ -441,14 +451,20 @@ impl NonUpperCaseGlobals { if name.chars().any(|c| c.is_lowercase()) { cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); - lint.build(&format!("{} `{}` should have an upper case name", sort, name)) - .span_suggestion( + let mut err = + lint.build(&format!("{} `{}` should have an upper case name", sort, name)); + // We cannot provide meaningful suggestions + // if the characters are in the category of "Lowercase Letter". + if name.to_string() != uc { + err.span_suggestion( ident.span, "convert the identifier to upper case", uc, Applicability::MaybeIncorrect, - ) - .emit(); + ); + } + + err.emit(); }) } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 1ee96f81e4fab..c8dbe68512857 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -22,7 +22,7 @@ use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; use rustc_hir::def_id; use rustc_middle::middle::stability; use rustc_middle::ty; -use rustc_session::lint::builtin::UNUSED_MACROS; +use rustc_session::lint::builtin::{SOFT_UNSTABLE, UNUSED_MACROS}; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::edition::Edition; @@ -459,22 +459,21 @@ impl<'a> Resolver<'a> { } // We are trying to avoid reporting this error if other related errors were reported. - if inner_attr + if res != Res::Err + && inner_attr && !self.session.features_untracked().custom_inner_attributes - && path != &sym::test - && res != Res::Err { - feature_err( - &self.session.parse_sess, - sym::custom_inner_attributes, - path.span, - match res { - Res::Def(..) => "inner macro attributes are unstable", - Res::NonMacroAttr(..) => "custom inner attributes are unstable", - _ => unreachable!(), - }, - ) - .emit(); + let msg = match res { + Res::Def(..) => "inner macro attributes are unstable", + Res::NonMacroAttr(..) => "custom inner attributes are unstable", + _ => unreachable!(), + }; + if path == &sym::test { + self.session.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg); + } else { + feature_err(&self.session.parse_sess, sym::custom_inner_attributes, path.span, msg) + .emit(); + } } Ok((ext, res)) diff --git a/config.toml.example b/config.toml.example index c9e183887504c..5b045d4e32d8d 100644 --- a/config.toml.example +++ b/config.toml.example @@ -446,6 +446,11 @@ changelog-seen = 2 # nightly features #channel = "dev" +# A descriptive string to be appended to `rustc --version` output, which is +# also used in places like debuginfo `DW_AT_producer`. This may be useful for +# supplementary build information, like distro-specific package versions. +#description = "" + # The root location of the musl installation directory. #musl-root = "..." diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 1512235da6a81..b9490c44f4b25 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -62,6 +62,13 @@ //! T` obtained from [`Box::::into_raw`] may be deallocated using the //! [`Global`] allocator with [`Layout::for_value(&*value)`]. //! +//! For zero-sized values, the `Box` pointer still has to be [valid] for reads +//! and writes and sufficiently aligned. In particular, casting any aligned +//! non-zero integer literal to a raw pointer produces a valid pointer, but a +//! pointer pointing into previously allocated memory that since got freed is +//! not valid. The recommended way to build a Box to a ZST if `Box::new` cannot +//! be used is to use [`ptr::NonNull::dangling`]. +//! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers //! (i.e. the C type `T*`). This means that if you have extern "C" @@ -125,6 +132,7 @@ //! [`Global`]: crate::alloc::Global //! [`Layout`]: crate::alloc::Layout //! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value +//! [valid]: ptr#safety #![stable(feature = "rust1", since = "1.0.0")] @@ -530,7 +538,10 @@ impl Box { /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// + /// The safety conditions are described in the [memory layout] section. + /// /// # Examples + /// /// Recreate a `Box` which was previously converted to a raw pointer /// using [`Box::into_raw`]: /// ``` diff --git a/library/backtrace b/library/backtrace index 8b8ea53b56f51..af078ecc0b069 160000 --- a/library/backtrace +++ b/library/backtrace @@ -1 +1 @@ -Subproject commit 8b8ea53b56f519dd7780defdd4254daaec892584 +Subproject commit af078ecc0b069ec594982f92d4c6c58af99efbb5 diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 9de2758767e3e..27d49529a5ec2 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -16,12 +16,16 @@ //! provided at this point are very minimal: //! //! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst]. -//! * All pointers (except for the null pointer) are valid for all operations of -//! [size zero][zst]. //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer //! be *dereferenceable*: the memory range of the given size starting at the pointer must all be //! within the bounds of a single allocated object. Note that in Rust, //! every (stack-allocated) variable is considered a separate allocated object. +//! * Even for operations of [size zero][zst], the pointer must not be pointing to deallocated +//! memory, i.e., deallocation makes pointers invalid even for zero-sized operations. However, +//! casting any non-zero integer *literal* to a pointer is valid for zero-sized accesses, even if +//! some memory happens to exist at that address and gets deallocated. This corresponds to writing +//! your own allocator: allocating zero-sized objects is not very hard. The canonical way to +//! obtain a pointer that is valid for zero-sized accesses is [`NonNull::dangling`]. //! * All accesses performed by functions in this module are *non-atomic* in the sense //! of [atomic operations] used to synchronize between threads. This means it is //! undefined behavior to perform two concurrent accesses to the same location from different diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c50aa18caf69a..83f22895237a8 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2599,6 +2599,34 @@ impl [T] { } } + /// Fills `self` with elements returned by calling a closure repeatedly. + /// + /// This method uses a closure to create new values. If you'd rather + /// [`Clone`] a given value, use [`fill`]. If you want to use the [`Default`] + /// trait to generate values, you can pass [`Default::default`] as the + /// argument. + /// + /// [`fill`]: #method.fill + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_fill_with)] + /// + /// let mut buf = vec![1; 10]; + /// buf.fill_with(Default::default); + /// assert_eq!(buf, vec![0; 10]); + /// ``` + #[unstable(feature = "slice_fill_with", issue = "79221")] + pub fn fill_with(&mut self, mut f: F) + where + F: FnMut() -> T, + { + for el in self { + *el = f(); + } + } + /// Copies the elements from `src` into `self`. /// /// The length of `src` must be the same as `self`. diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index ad9d1238370ec..71d00b5c08735 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -23,14 +23,14 @@ unwind = { path = "../unwind" } hashbrown = { version = "0.9.0", default-features = false, features = ['rustc-dep-of-std'] } # Dependencies of the `backtrace` crate -addr2line = { version = "0.13.0", optional = true, default-features = false } +addr2line = { version = "0.14.0", optional = true, default-features = false } rustc-demangle = { version = "0.1.18", features = ['rustc-dep-of-std'] } miniz_oxide = { version = "0.4.0", optional = true, default-features = false } [dependencies.object] -version = "0.20" +version = "0.22" optional = true default-features = false -features = ['read_core', 'elf', 'macho', 'pe'] +features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] [dev-dependencies] rand = "0.7" diff --git a/library/std/src/num/tests.rs b/library/std/src/num/tests.rs index 2f50b73f4907f..df0df3f23f756 100644 --- a/library/std/src/num/tests.rs +++ b/library/std/src/num/tests.rs @@ -75,8 +75,8 @@ fn test_checked_mul() { macro_rules! test_is_power_of_two { ($test_name:ident, $T:ident) => { + #[test] fn $test_name() { - #![test] assert_eq!((0 as $T).is_power_of_two(), false); assert_eq!((1 as $T).is_power_of_two(), true); assert_eq!((2 as $T).is_power_of_two(), true); @@ -96,8 +96,8 @@ test_is_power_of_two! { test_is_power_of_two_uint, usize } macro_rules! test_next_power_of_two { ($test_name:ident, $T:ident) => { + #[test] fn $test_name() { - #![test] assert_eq!((0 as $T).next_power_of_two(), 1); let mut next_power = 1; for i in 1 as $T..40 { @@ -118,8 +118,8 @@ test_next_power_of_two! { test_next_power_of_two_uint, usize } macro_rules! test_checked_next_power_of_two { ($test_name:ident, $T:ident) => { + #[test] fn $test_name() { - #![test] assert_eq!((0 as $T).checked_next_power_of_two(), Some(1)); let smax = $T::MAX >> 1; assert_eq!(smax.checked_next_power_of_two(), Some(smax + 1)); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 2c2efaa9eb4aa..9fcbe8e1e3564 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -152,6 +152,7 @@ pub struct Config { // misc pub low_priority: bool, pub channel: String, + pub description: Option, pub verbose_tests: bool, pub save_toolstates: Option, pub print_step_timings: bool, @@ -470,6 +471,7 @@ struct Rust { parallel_compiler: Option, default_linker: Option, channel: Option, + description: Option, musl_root: Option, rpath: Option, verbose_tests: Option, @@ -841,6 +843,7 @@ impl Config { .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); set(&mut config.backtrace, rust.backtrace); set(&mut config.channel, rust.channel); + config.description = rust.description; set(&mut config.rust_dist_src, rust.dist_src); set(&mut config.verbose_tests, rust.verbose_tests); // in the case "false" is set explicitly, do not overwrite the command line args diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 322e9d6923295..42f00ce962174 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -146,6 +146,7 @@ def v(*args): v("experimental-targets", "llvm.experimental-targets", "experimental LLVM targets to build") v("release-channel", "rust.channel", "the name of the release channel to build") +v("release-description", "rust.description", "optional descriptive string for version output") # Used on systems where "cc" is unavailable v("default-linker", "rust.default-linker", "the default linker") diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ca140b9d27828..06ccd72186dd1 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1082,7 +1082,13 @@ impl Build { /// Note that this is a descriptive string which includes the commit date, /// sha, version, etc. fn rust_version(&self) -> String { - self.rust_info.version(self, &self.version) + let mut version = self.rust_info.version(self, &self.version); + if let Some(ref s) = self.config.description { + version.push_str(" ("); + version.push_str(s); + version.push_str(")"); + } + version } /// Returns the full commit hash. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 57013e9194bc1..dd19861573667 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -18,4 +18,5 @@ - [Known Issues](targets/known-issues.md) - [Profile-guided Optimization](profile-guided-optimization.md) - [Linker-plugin based LTO](linker-plugin-lto.md) +- [Exploit Mitigations](exploit-mitigations.md) - [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md new file mode 100644 index 0000000000000..5e23b91193f88 --- /dev/null +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -0,0 +1,693 @@ +# Exploit Mitigations + +This chapter documents the exploit mitigations supported by the Rust +compiler, and is by no means an extensive survey of the Rust programming +language’s security features. + +This chapter is for software engineers working with the Rust programming +language, and assumes prior knowledge of the Rust programming language and +its toolchain. + + +## Introduction + +The Rust programming language provides memory[1] and thread[2] safety +guarantees via its ownership[3], references and borrowing[4], and slice +types[5] features. However, Unsafe Rust[6] introduces unsafe blocks, unsafe +functions and methods, unsafe traits, and new types that are not subject to +the borrowing rules. + +Parts of the Rust standard library are implemented as safe abstractions over +unsafe code (and historically have been vulnerable to memory corruption[7]). +Furthermore, the Rust code and documentation encourage creating safe +abstractions over unsafe code. This can cause a false sense of security if +unsafe code is not properly reviewed and tested. + +Unsafe Rust introduces features that do not provide the same memory and +thread safety guarantees. This causes programs or libraries to be +susceptible to memory corruption (CWE-119)[8] and concurrency issues +(CWE-557)[9]. Modern C and C++ compilers provide exploit mitigations to +increase the difficulty to exploit vulnerabilities resulting from these +issues. Therefore, the Rust compiler must also support these exploit +mitigations in order to mitigate vulnerabilities resulting from the use of +Unsafe Rust. This chapter documents these exploit mitigations and how they +apply to Rust. + +This chapter does not discuss the effectiveness of these exploit mitigations +as they vary greatly depending on several factors besides their design and +implementation, but rather describe what they do, so their effectiveness can +be understood within a given context. + + +## Exploit mitigations + +This section documents the exploit mitigations applicable to the Rust +compiler when building programs for the Linux operating system on the AMD64 +architecture and equivalent.1 + +The Rust Programming Language currently has no specification. The Rust +compiler (i.e., rustc) is the language reference implementation. All +references to “the Rust compiler” in this chapter refer to the language +reference implementation. + +Table I \ +Summary of exploit mitigations supported by the Rust compiler when building +programs for the Linux operating system on the AMD64 architecture and +equivalent. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Exploit mitigation + Supported and enabled by default + Since +
Position-independent executable + Yes + 0.12.0 (2014-10-09) +
Integer overflow checks + Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) + 1.1.0 (2015-06-25) +
Non-executable memory regions + Yes + 1.8.0 (2016-04-14) +
Stack clashing protection + Yes + 1.20.0 (2017-08-31) +
Read-only relocations and immediate binding + Yes + 1.21.0 (2017-10-12) +
Heap corruption protection + Yes + 1.32.0 (2019-01-17) (via operating system default or specified allocator) +
Stack smashing protection + No + +
Forward-edge control flow protection + No + +
Backward-edge control flow protection (e.g., shadow and safe stack) + No + +
+ +1\. See + +for a list of targets and their default options. + + +### Position-independent executable + +Position-independent executable increases the difficulty of the use of code +reuse exploitation techniques, such as return-oriented programming (ROP) and +variants, by generating position-independent code for the executable, and +instructing the dynamic linker to load it similarly to a shared object at a +random load address, thus also benefiting from address-space layout +randomization (ASLR). This is also referred to as “full ASLR”. + +The Rust compiler supports position-independent executable, and enables it +by default since version 0.12.0 (2014-10-09)[10]–[13]. + +```text +$ readelf -h target/release/hello-rust | grep Type: + Type: DYN (Shared object file) +``` +Fig. 1. Checking if an executable is a position-independent executable. + +An executable with an object type of `ET_DYN` (i.e., shared object) and not +`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. +1). + + +### Integer overflow checks + +Integer overflow checks protects programs from undefined and unintended +behavior (which may cause vulnerabilities) by checking for results of signed +and unsigned integer computations that cannot be represented in their type, +resulting in an overflow or wraparound. + +The Rust compiler supports integer overflow checks, and enables it when +debug assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20]. + +```compile_fail +fn main() { + let u: u8 = 255; + println!("u: {}", u + 1); +} +``` +Fig. 2. hello-rust-integer program. + +```text +$ cargo run + Compiling hello-rust-integer v0.1.0 (/home/rcvalle/hello-rust-integer) + Finished dev [unoptimized + debuginfo] target(s) in 0.23s + Running `target/debug/hello-rust-integer` +thread 'main' panicked at 'attempt to add with overflow', src/main.rs:3:23 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. +``` +Fig. 3. Build and execution of hello-rust-integer with debug assertions +enabled. + +```text +$ cargo run --release + Compiling hello-rust-integer v0.1.0 (/home/rcvalle/hello-rust-integer) + Finished release [optimized] target(s) in 0.23s + Running `target/release/hello-rust-integer` +u: 0 +``` +Fig. 4. Build and execution of hello-rust-integer with debug assertions +disabled. + +Integer overflow checks are enabled when debug assertions are enabled (see +Fig. 3), and disabled when debug assertions are disabled (see Fig. 4). To +enable integer overflow checks independently, use the option to control +integer overflow checks, scoped attributes, or explicit checking methods +such as `checked_add`2. + +It is recommended that explicit wrapping methods such as `wrapping_add` be +used when wrapping semantics are intended, and that explicit checking and +wrapping methods always be used when using Unsafe Rust. + +2\. See +for more information on the checked, overflowing, saturating, and wrapping +methods (using u32 as an example). + + +### Non-executable memory regions + +Non-executable memory regions increase the difficulty of exploitation by +limiting the memory regions that can be used to execute arbitrary code. Most +modern processors provide support for the operating system to mark memory +regions as non executable, but it was previously emulated by software, such +as in grsecurity/PaX's +[PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) and +[SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors that +did not provide support for it. This is also known as “No Execute (NX) Bit”, +“Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others. + +The Rust compiler supports non-executable memory regions, and enables it by +default since its initial release, version 0.1 (2012-01-20)[21], [22], but +has regressed since then[23]–[25], and enforced by default since version +1.8.0 (2016-04-14)[25]. + +```text +$ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK + GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 + 0x0000000000000000 0x0000000000000000 RW 0x10 +``` +Fig. 5. Checking if non-executable memory regions are enabled for a given +binary. + +The presence of an element of type `PT_GNU_STACK` in the program header +table with the `PF_X` (i.e., executable) flag unset indicates non-executable +memory regions3 are enabled for a given binary (see Fig. 5). +Conversely, the presence of an element of type `PT_GNU_STACK` in the program +header table with the `PF_X` flag set or the absence of an element of type +`PT_GNU_STACK` in the program header table indicates non-executable memory +regions are not enabled for a given binary. + +3\. See the Appendix section for more information on why it +affects other memory regions besides the stack. + + +### Stack clashing protection + +Stack clashing protection protects the stack from overlapping with another +memory region—allowing arbitrary data in both to be overwritten using each +other—by reading from the stack pages as the stack grows to cause a page +fault when attempting to read from the guard page/region. This is also +referred to as “stack probes” or “stack probing”. + +The Rust compiler supports stack clashing protection via stack probing, and +enables it by default since version 1.20.0 (2017-08-31)[26]–[29]. + +![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.") +Fig. 6. IDA Pro listing cross references to `__rust_probestack` in +hello-rust. + +```rust +fn hello() { + println!("Hello, world!"); +} + +fn main() { + let _: [u64; 1024] = [0; 1024]; + hello(); +} +``` +Fig 7. Modified hello-rust. + +![Screenshot of IDA Pro listing cross references to __rust_probestack in modified hello-rust.](images/image2.png "Cross references to __rust_probestack in modified hello-rust.") +Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified +hello-rust. + +To check if stack clashing protection is enabled for a given binary, search +for cross references to `__rust_probestack`. The `__rust_probestack` is +called in the prologue of functions whose stack size is larger than a page +size (see Fig. 6), and can be forced for illustration purposes by modifying +the hello-rust example as seen in Fig. 7 and Fig. 8. + + +### Read-only relocations and immediate binding + +**Read-only relocations** protect segments containing relocations and +relocation information (i.e., `.init_array`, `.fini_array`, `.dynamic`, and +`.got`) from being overwritten by marking these segments read only. This is +also referred to as “partial RELRO”. + +The Rust compiler supports read-only relocations, and enables it by default +since version 1.21.0 (2017-10-12)[30], [31]. + +```text +$ readelf -l target/release/hello-rust | grep GNU_RELRO + GNU_RELRO 0x000000000002ee00 0x000000000002fe00 0x000000000002fe00 +``` +Fig. 9. Checking if read-only relocations is enabled for a given binary. + +The presence of an element of type `PT_GNU_RELRO` in the program header +table indicates read-only relocations are enabled for a given binary (see +Fig. 9). Conversely, the absence of an element of type `PT_GNU_RELRO` in the +program header table indicates read-only relocations are not enabled for a +given binary. + +**Immediate binding** protects additional segments containing relocations +(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker +to perform all relocations before transferring control to the program during +startup, so all segments containing relocations can be marked read only +(when combined with read-only relocations). This is also referred to as +“full RELRO”. + +The Rust compiler supports immediate binding, and enables it by default +since version 1.21.0 (2017-10-12)[30], [31]. + +```text +$ readelf -d target/release/hello-rust | grep BIND_NOW + 0x000000000000001e (FLAGS) BIND_NOW +``` +Fig. 10. Checking if immediate binding is enabled for a given binary. + +The presence of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` +flag4 in the dynamic section indicates immediate +binding is enabled for a given binary (see Fig. 10). Conversely, the absence +of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the +dynamic section indicates immediate binding is not enabled for a given +binary. + +The presence of both an element of type `PT_GNU_RELRO` in the program header +table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` +flag in the dynamic section indicates full RELRO is enabled for a given +binary (see Fig. 9 and Fig. 10). + +4\. And the `DF_1_NOW` flag for some link editors. + + +### Heap corruption protection + +Heap corruption protection protects memory allocated dynamically by +performing several checks, such as checks for corrupted links between list +elements, invalid pointers, invalid sizes, double/multiple “frees” of the +same memory allocated, and many corner cases of these. These checks are +implementation specific, and vary per allocator. + +[ARM Memory Tagging Extension +(MTE)](https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety), +when available, will provide hardware assistance for a probabilistic +mitigation to detect memory safety violations by tagging memory allocations, +and automatically checking that the correct tag is used on every memory +access. + +Rust’s default allocator has historically been +[jemalloc](http://jemalloc.net/), and it has long been the cause of issues +and the subject of much discussion[32]–[38]. Consequently, it has been +removed as the default allocator in favor of the operating system’s standard +C library default allocator5 since version 1.32.0 +(2019-01-17)[39]. + +```should_panic +fn main() { + let mut x = Box::new([0; 1024]); + + for i in 0..1026 { + unsafe { + let elem = x.get_unchecked_mut(i); + *elem = 0x4141414141414141u64; + } + } +} +``` +Fig. 11. hello-rust-heap program. + +```text +$ cargo run + Compiling hello-rust-heap v0.1.0 (/home/rcvalle/hello-rust-heap) + Finished dev [unoptimized + debuginfo] target(s) in 0.25s + Running `target/debug/hello-rust-heap` +free(): invalid next size (normal) +Aborted +``` +Fig. 12. Build and execution of hello-rust-heap with debug assertions +enabled. + +```text +$ cargo run --release + Compiling hello-rust-heap v0.1.0 (/home/rcvalle/hello-rust-heap) + Finished release [optimized] target(s) in 0.25s + Running `target/release/hello-rust-heap` +free(): invalid next size (normal) +Aborted +``` +Fig. 13. Build and execution of hello-rust-heap with debug assertions +disabled. + +Heap corruption checks are being performed when using the default allocator +(i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13. + +5\. Linux's standard C library default allocator is the GNU +Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram +Gloger, which in turn is derived from dlmalloc (Doug Lea malloc) by Doug +Lea. + + +### Stack smashing protection + +Stack smashing protection protects programs from stack-based buffer +overflows by inserting a random guard value between local variables and the +saved return instruction pointer, and checking if this value has changed +when returning from a function. This is also known as “Stack Protector” or +“Stack Smashing Protector (SSP)”. + +The Rust compiler does not support stack smashing protection. However, more +comprehensive alternatives to stack smashing protection exist, such as +shadow and safe stack (see backward-edge control flow protection). + +![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.") +Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in +hello-rust. + +To check if stack smashing protection is enabled for a given binary, search +for cross references to `__stack_chk_fail`. The only cross references to +`__stack_chk_fail` in hello-rust are from the statically-linked libbacktrace +library (see Fig. 14). + + +### Forward-edge control flow protection + +Forward-edge control flow protection protects programs from having its +control flow changed/hijacked by performing checks to ensure that +destinations of indirect branches are one of their valid destinations in the +control flow graph. The comprehensiveness of these checks vary per +implementation. This is also known as “forward-edge control flow integrity +(CFI)”. + +Newer processors provide hardware assistance for forward-edge control flow +protection, such as ARM Branch Target Identification (BTI), ARM Pointer +Authentication, and Intel Indirect Branch Tracking (IBT) as part of Intel +Control-flow Enforcement Technology (CET). However, ARM BTI and Intel IBT +-based implementations are less comprehensive than software-based +implementations such as [LLVM ControlFlowIntegrity +(CFI)](https://clang.llvm.org/docs/ControlFlowIntegrity.html), and the +commercially available [grsecurity/PaX Reuse Attack Protector +(RAP)](https://grsecurity.net/rap_faq). + +The Rust compiler does not support forward-edge control flow protection on +Linux6. There is work currently ongoing to add support +for the [sanitizers](https://github.com/google/sanitizers)[40], which may or +may not include support for LLVM CFI. + +```text +$ readelf -s target/release/hello-rust | grep __cfi_init +``` +Fig. 15. Checking if LLVM CFI is enabled for a given binary. + +The presence of the `__cfi_init` symbol (and references to `__cfi_check`) +indicates that LLVM CFI (i.e., forward-edge control flow protection) is +enabled for a given binary. Conversely, the absence of the `__cfi_init` +symbol (and references to `__cfi_check`) indicates that LLVM CFI is not +enabled for a given binary (see Fig. 15). + +6\. It supports Control Flow Guard (CFG) on Windows (see +). + + +### Backward-edge control flow protection + +**Shadow stack** protects saved return instruction pointers from being +overwritten by storing a copy of them on a separate (shadow) stack, and +using these copies as authoritative values when returning from functions. +This is also known as “ShadowCallStack” and “Return Flow Guard”, and is +considered an implementation of backward-edge control flow protection (or +“backward-edge CFI”). + +**Safe stack** protects not only the saved return instruction pointers, but +also register spills and some local variables from being overwritten by +storing unsafe variables, such as large arrays, on a separate (unsafe) +stack, and using these unsafe variables on the separate stack instead. This +is also known as “SafeStack”, and is also considered an implementation of +backward-edge control flow protection. + +Both shadow and safe stack are intended to be a more comprehensive +alternatives to stack smashing protection as they protect the saved return +instruction pointers (and other data in the case of safe stack) from +arbitrary writes and non-linear out-of-bounds writes. + +Newer processors provide hardware assistance for backward-edge control flow +protection, such as ARM Pointer Authentication, and Intel Shadow Stack as +part of Intel CET. + +The Rust compiler does not support shadow or safe stack. There is work +currently ongoing to add support for the sanitizers[40], which may or may +not include support for safe stack7. + +```text +$ readelf -s target/release/hello-rust | grep __safestack_init +``` +Fig. 16. Checking if LLVM SafeStack is enabled for a given binary. + +The presence of the `__safestack_init` symbol indicates that LLVM SafeStack +is enabled for a given binary. Conversely, the absence of the +`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a +given binary (see Fig. 16). + +7\. The shadow stack implementation for the AMD64 +architecture and equivalent in LLVM was removed due to performance and +security issues. + + +## Appendix + +As of the latest version of the [Linux Standard Base (LSB) Core +Specification](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/progheader.html), +the `PT_GNU_STACK` program header indicates whether the stack should be +executable, and the absence of this header indicates that the stack should +be executable. However, the Linux kernel currently sets the +`READ_IMPLIES_EXEC` personality upon loading any executable with the +`PT_GNU_STACK` program header and the `PF_X `flag set or with the absence of +this header, resulting in not only the stack, but also all readable virtual +memory mappings being executable. + +An attempt to fix this [was made in +2012](https://lore.kernel.org/lkml/f298f914-2239-44e4-8aa1-a51282e7fac0@zmail15.collab.prod.int.phx2.redhat.com/), +and another [was made in +2020](https://lore.kernel.org/kernel-hardening/20200327064820.12602-1-keescook@chromium.org/). +The former never landed, and the latter partially fixed it, but introduced +other issues—the absence of the `PT_GNU_STACK` program header still causes +not only the stack, but also all readable virtual memory mappings to be +executable in some architectures, such as IA-32 and equivalent (or causes +the stack to be non-executable in some architectures, such as AMD64 and +equivalent, contradicting the LSB). + +The `READ_IMPLIES_EXEC` personality needs to be completely separated from +the `PT_GNU_STACK` program header by having a separate option for it (or +setarch -X could just be used whenever `READ_IMPLIES_EXEC` is needed), and +the absence of the `PT_GNU_STACK` program header needs to have more secure +defaults (unrelated to `READ_IMPLIES_EXEC`). + + +## References + +1. D. Hosfelt. “Fearless security: memory safety.” Mozilla Hacks. + . + +2. D. Hosfelt. “Fearless security: thread safety.” Mozilla Hacks. + . + +3. S. Klabnik and C. Nichols. “What Is Ownership?.” The Rust Programming + Language. . + +4. S. Klabnik and C. Nichols. “References and Borrowing.” The Rust + Programming Language. + . + +5. S. Klabnik and C. Nichols. “The Slice Type.” The Rust Programming + Language. . + +6. S. Klabnik and C. Nichols. “Unsafe Rust.” The Rust Programming Language. + . + +7. S. Davidoff. “How Rust’s standard library was vulnerable for years and + nobody noticed.” Medium. + . + +8. “Improper restriction of operations within the bounds of a memory buffer + (CWE-119).” MITRE CWE List. + . + +9. “Concurrency issues (CWE-557).” MITRE CWE List. + . + +10. K. McAllister. “Memory exploit mitigations #15179.” GitHub. + . + +11. K. McAllister. “RFC: Memory exploit mitigation #145.” GitHub. + . + +12. K. McAllister. “RFC: Memory exploit mitigation.” GitHub. + . + +13. D. Micay. “Enable PIE by default on Linux for full ASLR #16340.” GitHub. + . + +14. N. Matsakis. “Integer overflow #560.” GitHub. + . + +15. G. Lehel and N. Matsakis. “Integer overflow.” GitHub. + . + +16. A. Turon. “Tracking issue for integer overflow (RFC 560) #22020.” + GitHub. . + +17. H. Wilson. “Myths and legends about integer overflow in Rust.” Huon on + the Internet. + . + +18. B. Anderson. “Stabilize -C overflow-checks #1535.” GitHub. + . + +19. B. Anderson. “Stable overflow checks.” GitHub. + . + +20. N. Froyd. “Add -C overflow-checks option #40037.” GitHub. + . + +21. R. Á. de Espíndola. “rustc requires executable stack #798.” GitHub. + . + +22. A. Seipp. “Make sure librustrt.so is linked with a non-executable stack. + #1066.” GitHub. . + +23. D. Micay. “Rust binaries should not have an executable stack #5643.” + GitHub. . + +24. D. Micay. “Mark the assembly object stacks as non-executable #5647.” + GitHub. . + +25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.” + GitHub. . + +26. “Replace stack overflow checking with stack probes #16012.” GitHub. + . + +27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and + clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub. + . + +28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub. + . + +29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub. + . + +30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by + default #29877.” GitHub. . + +31. J. Löthberg. “Add support for full RELRO #43170.” GitHub. + . + +32. N. Matsakis. “Allocators in Rust.” Baby Steps. + . + +33. A. Crichton. “RFC: Allow changing the default allocator #1183.” GitHub. + . + +34. A. Crichton. “RFC: Swap out jemalloc.” GitHub. + . + +35. A. Crichton. “Tracking issue for changing the global, default allocator + (RFC 1974) #27389.” GitHub. + . + +36. S. Fackler. “Prepare global allocators for stabilization #1974.” GitHub. + . + +37. A. Crichton. “RFC: Global allocators.” GitHub. + . + +38. B. Anderson. “Switch the default global allocator to System, remove + alloc\_jemalloc, use jemallocator in rustc #36963.” GitHub. + . + +39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub. + . + +40. J. Aparicio. 2017. “Tracking issue for sanitizer support #39699.” + . diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png new file mode 100644 index 0000000000000..ee2d3fd4f43c6 Binary files /dev/null and b/src/doc/rustc/src/images/image1.png differ diff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png new file mode 100644 index 0000000000000..03061e1f0b12d Binary files /dev/null and b/src/doc/rustc/src/images/image2.png differ diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png new file mode 100644 index 0000000000000..a49e14b5ed222 Binary files /dev/null and b/src/doc/rustc/src/images/image3.png differ diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs index d343746955f39..ee3fe712e36e5 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.rs @@ -1,5 +1,6 @@ // The non-crate level cases are in issue-43106-gating-of-builtin-attrs.rs. +#![allow(soft_unstable)] #![test = "4200"] //~^ ERROR cannot determine resolution for the attribute macro `test` diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr index a7d3a1e16840e..335af5e7905f2 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-test.stderr @@ -1,5 +1,5 @@ error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-43106-gating-of-test.rs:3:4 + --> $DIR/issue-43106-gating-of-test.rs:4:4 | LL | #![test = "4200"] | ^^^^ diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs index fa692db4bf66c..1ed2d330b5123 100644 --- a/src/test/ui/issues/issue-28134.rs +++ b/src/test/ui/issues/issue-28134.rs @@ -1,3 +1,4 @@ // compile-flags: --test +#![allow(soft_unstable)] #![test] //~ ERROR cannot determine resolution for the attribute macro `test` diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr index 5f8d27dd043b1..8ed4d015f3216 100644 --- a/src/test/ui/issues/issue-28134.stderr +++ b/src/test/ui/issues/issue-28134.stderr @@ -1,5 +1,5 @@ error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-28134.rs:3:4 + --> $DIR/issue-28134.rs:4:4 | LL | #![test] | ^^^^ diff --git a/src/test/ui/lint/special-upper-lower-cases.rs b/src/test/ui/lint/special-upper-lower-cases.rs new file mode 100644 index 0000000000000..71ebf05dd31ab --- /dev/null +++ b/src/test/ui/lint/special-upper-lower-cases.rs @@ -0,0 +1,24 @@ +// (#77273) These characters are in the general categories of +// "Uppercase/Lowercase Letter". +// The diagnostics don't provide meaningful suggestions for them +// as we cannot convert them properly. + +// check-pass + +#![feature(non_ascii_idents)] +#![allow(uncommon_codepoints, unused)] + +struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝; +//~^ WARN: type `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + +// FIXME: How we should handle this? +struct 𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝; +//~^ WARN: type `𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + +static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1; +//~^ WARN: static variable `𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲` should have an upper case name + +fn main() { + let 𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢 = 1; + //~^ WARN: variable `𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢` should have a snake case name +} diff --git a/src/test/ui/lint/special-upper-lower-cases.stderr b/src/test/ui/lint/special-upper-lower-cases.stderr new file mode 100644 index 0000000000000..f32193a2e4a47 --- /dev/null +++ b/src/test/ui/lint/special-upper-lower-cases.stderr @@ -0,0 +1,32 @@ +warning: type `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + --> $DIR/special-upper-lower-cases.rs:11:8 + | +LL | struct 𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝; + | ^^^^^^^^^ + | + = note: `#[warn(non_camel_case_types)]` on by default + +warning: type `𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝` should have an upper camel case name + --> $DIR/special-upper-lower-cases.rs:15:8 + | +LL | struct 𝕟𝕠𝕥_𝕒_𝕔𝕒𝕞𝕖𝕝; + | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `𝕟𝕠𝕥𝕒𝕔𝕒𝕞𝕖𝕝` + +warning: static variable `𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲` should have an upper case name + --> $DIR/special-upper-lower-cases.rs:18:8 + | +LL | static 𝗻𝗼𝗻𝘂𝗽𝗽𝗲𝗿𝗰𝗮𝘀𝗲: i32 = 1; + | ^^^^^^^^^^^^ + | + = note: `#[warn(non_upper_case_globals)]` on by default + +warning: variable `𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢` should have a snake case name + --> $DIR/special-upper-lower-cases.rs:22:9 + | +LL | let 𝓢𝓝𝓐𝓐𝓐𝓐𝓚𝓔𝓢 = 1; + | ^^^^^^^^^ + | + = note: `#[warn(non_snake_case)]` on by default + +warning: 4 warnings emitted + diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs index 4c72ecbfc03a8..e2cf4e7398756 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.rs +++ b/src/test/ui/proc-macro/proc-macro-gates.rs @@ -45,4 +45,9 @@ fn attrs() { //~^ ERROR: custom attributes cannot be applied to expressions } +fn test_case() { + #![test] //~ ERROR inner macro attributes are unstable + //~| WARN this was previously accepted +} + fn main() {} diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr index 33a808037eea5..118213a17d462 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.stderr +++ b/src/test/ui/proc-macro/proc-macro-gates.stderr @@ -76,6 +76,16 @@ LL | let _x = #[identity_attr] println!(); = note: see issue #54727 for more information = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable -error: aborting due to 9 previous errors +error: inner macro attributes are unstable + --> $DIR/proc-macro-gates.rs:49:8 + | +LL | #![test] + | ^^^^ + | + = note: `#[deny(soft_unstable)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/miri b/src/tools/miri index c8f51fc5a772a..746ea5b141baf 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit c8f51fc5a772a125f3b3ad7fe46609a4638ca509 +Subproject commit 746ea5b141baf1f86c2ad17753a37b135e0c1aa3