add realtime sanitizer

This commit is contained in:
Lucas Baumann 2025-05-23 14:35:28 +02:00 committed by Lucas Baumann
parent bc883e24b8
commit d198633b95
34 changed files with 240 additions and 38 deletions

View file

@ -1,4 +1,4 @@
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy};
use rustc_session::parse::feature_err;
use super::prelude::*;
@ -592,7 +592,8 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
r#"memory = "on|off""#,
r#"memtag = "on|off""#,
r#"shadow_call_stack = "on|off""#,
r#"thread = "on|off""#
r#"thread = "on|off""#,
r#"realtime = "nonblocking|blocking|caller""#,
]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
@ -606,6 +607,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
let mut on_set = SanitizerSet::empty();
let mut off_set = SanitizerSet::empty();
let mut rtsan = None;
for item in list.mixed() {
let Some(item) = item.meta_item() else {
@ -654,6 +656,17 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
Some(sym::thread) => apply(SanitizerSet::THREAD),
Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
Some(sym::realtime) => match value.value_as_str() {
Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking),
Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking),
Some(sym::caller) => rtsan = Some(RtsanSetting::Caller),
_ => {
cx.expected_specific_argument_strings(
value.value_span,
&[sym::nonblocking, sym::blocking, sym::caller],
);
}
},
_ => {
cx.expected_specific_argument_strings(
item.path().span(),
@ -666,6 +679,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
sym::shadow_call_stack,
sym::thread,
sym::hwaddress,
sym::realtime,
],
);
continue;
@ -673,7 +687,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
}
}
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
Some(AttributeKind::Sanitize { on_set, off_set, rtsan, span: cx.attr_span })
}
}

View file

@ -1,5 +1,5 @@
//! Set and unset common attributes on LLVM values.
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSetting};
use rustc_hir::def_id::DefId;
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs,
@ -131,6 +131,18 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>(
if enabled.contains(SanitizerSet::SAFESTACK) {
attrs.push(llvm::AttributeKind::SanitizeSafeStack.create_attr(cx.llcx));
}
if tcx.sess.sanitizers().contains(SanitizerSet::REALTIME) {
match sanitizer_fn_attr.rtsan_setting {
RtsanSetting::Nonblocking => {
attrs.push(llvm::AttributeKind::SanitizeRealtimeNonblocking.create_attr(cx.llcx))
}
RtsanSetting::Blocking => {
attrs.push(llvm::AttributeKind::SanitizeRealtimeBlocking.create_attr(cx.llcx))
}
// caller is the default, so no llvm attribute
RtsanSetting::Caller => (),
}
}
attrs
}

View file

@ -633,6 +633,7 @@ pub(crate) unsafe fn llvm_optimize(
sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
sanitize_memory_track_origins: config.sanitizer_memory_track_origins as c_int,
sanitize_realtime: config.sanitizer.contains(SanitizerSet::REALTIME),
sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD),
sanitize_hwaddress: config.sanitizer.contains(SanitizerSet::HWADDRESS),
sanitize_hwaddress_recover: config.sanitizer_recover.contains(SanitizerSet::HWADDRESS),

View file

@ -290,6 +290,8 @@ pub(crate) enum AttributeKind {
DeadOnReturn = 44,
CapturesReadOnly = 45,
CapturesNone = 46,
SanitizeRealtimeNonblocking = 47,
SanitizeRealtimeBlocking = 48,
}
/// LLVMIntPredicate
@ -482,6 +484,7 @@ pub(crate) struct SanitizerOptions {
pub sanitize_memory: bool,
pub sanitize_memory_recover: bool,
pub sanitize_memory_track_origins: c_int,
pub sanitize_realtime: bool,
pub sanitize_thread: bool,
pub sanitize_hwaddress: bool,
pub sanitize_hwaddress_recover: bool,

View file

@ -1252,6 +1252,9 @@ fn add_sanitizer_libraries(
if sanitizer.contains(SanitizerSet::SAFESTACK) {
link_sanitizer_runtime(sess, flavor, linker, "safestack");
}
if sanitizer.contains(SanitizerSet::REALTIME) {
link_sanitizer_runtime(sess, flavor, linker, "rtsan");
}
}
fn link_sanitizer_runtime(

View file

@ -349,9 +349,10 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
codegen_fn_attrs.alignment =
Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);
// Compute the disabled sanitizers.
codegen_fn_attrs.sanitizers.disabled |=
tcx.sanitizer_settings_for(did).disabled;
// Passed in sanitizer settings are always the default.
assert!(codegen_fn_attrs.sanitizers == SanitizerFnAttrs::default());
// Replace with #[sanitize] value
codegen_fn_attrs.sanitizers = tcx.sanitizer_settings_for(did);
// On trait methods, inherit the `#[align]` of the trait's method prototype.
codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did));
@ -587,7 +588,7 @@ fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs
};
// Check for a sanitize annotation directly on this def.
if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
if let Some((on_set, off_set, rtsan)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, rtsan, ..} => (on_set, off_set, rtsan))
{
// the on set is the set of sanitizers explicitly enabled.
// we mask those out since we want the set of disabled sanitizers here
@ -598,6 +599,11 @@ fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs
// the on set and off set are distjoint since there's a third option: unset.
// a node may not set the sanitizer setting in which case it inherits from parents.
// the code above in this function does this backtracking
// if rtsan was specified here override the parent
if let Some(rtsan) = rtsan {
settings.rtsan_setting = *rtsan;
}
}
settings
}

View file

@ -382,6 +382,16 @@ pub struct DebugVisualizer {
pub path: Symbol,
}
#[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)]
#[derive(HashStable_Generic, PrintAttribute)]
#[derive_const(Default)]
pub enum RtsanSetting {
Nonblocking,
Blocking,
#[default]
Caller,
}
/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
@ -689,7 +699,13 @@ pub enum AttributeKind {
///
/// the on set and off set are distjoint since there's a third option: unset.
/// a node may not set the sanitizer setting in which case it inherits from parents.
Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span },
/// rtsan is unset if None
Sanitize {
on_set: SanitizerSet,
off_set: SanitizerSet,
rtsan: Option<RtsanSetting>,
span: Span,
},
/// Represents `#[should_panic]`
ShouldPanic { reason: Option<Symbol>, span: Span },

View file

@ -6,6 +6,9 @@
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(derive_const)]
#![feature(exhaustive_patterns)]
#![feature(never_type)]
#![feature(variant_count)]

View file

@ -38,6 +38,7 @@
#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/InstrProfiling.h"
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
#include "llvm/Transforms/Scalar/AnnotationRemarks.h"
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
@ -531,6 +532,7 @@ struct LLVMRustSanitizerOptions {
bool SanitizeMemory;
bool SanitizeMemoryRecover;
int SanitizeMemoryTrackOrigins;
bool SanitizerRealtime;
bool SanitizeThread;
bool SanitizeHWAddress;
bool SanitizeHWAddressRecover;
@ -786,6 +788,13 @@ extern "C" LLVMRustResult LLVMRustOptimize(
MPM.addPass(HWAddressSanitizerPass(opts));
});
}
if (SanitizerOptions->SanitizerRealtime) {
OptimizerLastEPCallbacks.push_back([](ModulePassManager &MPM,
OptimizationLevel Level,
ThinOrFullLTOPhase phase) {
MPM.addPass(RealtimeSanitizerPass());
});
}
}
ModulePassManager MPM;

View file

@ -246,6 +246,8 @@ enum class LLVMRustAttributeKind {
DeadOnReturn = 44,
CapturesReadOnly = 45,
CapturesNone = 46,
SanitizeRealtimeNonblocking = 47,
SanitizeRealtimeBlocking = 48,
};
static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
@ -342,6 +344,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
case LLVMRustAttributeKind::CapturesReadOnly:
case LLVMRustAttributeKind::CapturesNone:
report_fatal_error("Should be handled separately");
case LLVMRustAttributeKind::SanitizeRealtimeNonblocking:
return Attribute::SanitizeRealtime;
case LLVMRustAttributeKind::SanitizeRealtimeBlocking:
return Attribute::SanitizeRealtimeBlocking;
}
report_fatal_error("bad LLVMRustAttributeKind");
}

View file

@ -1,7 +1,7 @@
use std::borrow::Cow;
use rustc_abi::Align;
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr, RtsanSetting};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::Symbol;
use rustc_target::spec::SanitizerSet;
@ -245,11 +245,11 @@ impl CodegenFnAttrs {
#[derive(Clone, Copy, Debug, HashStable, TyEncodable, TyDecodable, Eq, PartialEq)]
pub struct SanitizerFnAttrs {
pub disabled: SanitizerSet,
pub rtsan_setting: RtsanSetting,
}
impl const Default for SanitizerFnAttrs {
fn default() -> Self {
Self { disabled: SanitizerSet::empty() }
Self { disabled: SanitizerSet::empty(), rtsan_setting: RtsanSetting::default() }
}
}

View file

@ -212,7 +212,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => {
self.check_custom_mir(dialect, phase, attr_span)
}
&Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => {
&Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, rtsan: _, span: attr_span}) => {
self.check_sanitize(attr_span, on_set | off_set, span, target);
},
Attribute::Parsed(AttributeKind::Link(_, attr_span)) => {

View file

@ -808,7 +808,7 @@ mod desc {
pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy;
pub(crate) const parse_oom_strategy: &str = "either `panic` or `abort`";
pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, or `thread`";
pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'";
pub(crate) const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
pub(crate) const parse_cfguard: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@ -1253,6 +1253,7 @@ pub mod parse {
"thread" => SanitizerSet::THREAD,
"hwaddress" => SanitizerSet::HWADDRESS,
"safestack" => SanitizerSet::SAFESTACK,
"realtime" => SanitizerSet::REALTIME,
_ => return false,
}
}

View file

@ -583,6 +583,7 @@ symbols! {
bitxor_assign,
black_box,
block,
blocking,
bool,
bool_then,
borrowck_graphviz_format,
@ -616,6 +617,7 @@ symbols! {
call_once,
call_once_future,
call_ref_future,
caller,
caller_location,
capture_disjoint_fields,
carrying_mul_add,
@ -1561,6 +1563,7 @@ symbols! {
non_exhaustive_omitted_patterns_lint,
non_lifetime_binders,
non_modrs_mods,
nonblocking,
none,
nontemporal_store,
noop_method_borrow,
@ -1801,6 +1804,7 @@ symbols! {
read_via_copy,
readonly,
realloc,
realtime,
reason,
reborrow,
receiver,

View file

@ -1177,6 +1177,7 @@ bitflags::bitflags! {
const KERNELADDRESS = 1 << 9;
const SAFESTACK = 1 << 10;
const DATAFLOW = 1 << 11;
const REALTIME = 1 << 12;
}
}
rustc_data_structures::external_bitflags_debug! { SanitizerSet }
@ -1227,6 +1228,7 @@ impl SanitizerSet {
SanitizerSet::SHADOWCALLSTACK => "shadow-call-stack",
SanitizerSet::THREAD => "thread",
SanitizerSet::HWADDRESS => "hwaddress",
SanitizerSet::REALTIME => "realtime",
_ => return None,
})
}
@ -1271,6 +1273,7 @@ impl FromStr for SanitizerSet {
"shadow-call-stack" => SanitizerSet::SHADOWCALLSTACK,
"thread" => SanitizerSet::THREAD,
"hwaddress" => SanitizerSet::HWADDRESS,
"realtime" => SanitizerSet::REALTIME,
s => return Err(format!("unknown sanitizer {s}")),
})
}

View file

@ -20,7 +20,10 @@ pub(crate) fn target() -> Target {
cpu: "apple-m1".into(),
max_atomic_width: Some(128),
// FIXME: The leak sanitizer currently fails the tests, see #88132.
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD,
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::CFI
| SanitizerSet::THREAD
| SanitizerSet::REALTIME,
supports_xray: true,
..opts
},

View file

@ -18,7 +18,9 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::THREAD
| SanitizerSet::REALTIME,
..opts
},
}

View file

@ -18,7 +18,9 @@ pub(crate) fn target() -> Target {
options: TargetOptions {
features: "+neon,+fp-armv8,+apple-a7".into(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS | SanitizerSet::THREAD,
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::THREAD
| SanitizerSet::REALTIME,
..opts
},
}

View file

@ -30,7 +30,8 @@ pub(crate) fn target() -> Target {
| SanitizerSet::MEMORY
| SanitizerSet::MEMTAG
| SanitizerSet::THREAD
| SanitizerSet::HWADDRESS,
| SanitizerSet::HWADDRESS
| SanitizerSet::REALTIME,
supports_xray: true,
..base::linux_gnu::opts()
},

View file

@ -21,7 +21,8 @@ pub(crate) fn target() -> Target {
supported_sanitizers: SanitizerSet::ADDRESS
| SanitizerSet::CFI
| SanitizerSet::LEAK
| SanitizerSet::THREAD,
| SanitizerSet::THREAD
| SanitizerSet::REALTIME,
supports_xray: true,
..opts
},

View file

@ -17,7 +17,8 @@ pub(crate) fn target() -> Target {
| SanitizerSet::LEAK
| SanitizerSet::MEMORY
| SanitizerSet::SAFESTACK
| SanitizerSet::THREAD;
| SanitizerSet::THREAD
| SanitizerSet::REALTIME;
base.supports_xray = true;
Target {

View file

@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasnt changed.
Last change is for: https://github.com/rust-lang/rust/pull/139931
Last change is for: https://github.com/rust-lang/rust/pull/147935

View file

@ -1262,13 +1262,13 @@ fn supported_sanitizers(
};
match &*target.triple {
"aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan"]),
"aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan"]),
"aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan", "rtsan"]),
"aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan", "rtsan"]),
"aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan", "rtsan"]),
"aarch64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
"aarch64-unknown-linux-gnu" => {
common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan", "rtsan"])
}
"aarch64-unknown-linux-ohos" => {
common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
@ -1276,7 +1276,7 @@ fn supported_sanitizers(
"loongarch64-unknown-linux-gnu" | "loongarch64-unknown-linux-musl" => {
common_libs("linux", "loongarch64", &["asan", "lsan", "msan", "tsan"])
}
"x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan", "rtsan"]),
"x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
"x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]),
"x86_64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
@ -1286,9 +1286,11 @@ fn supported_sanitizers(
}
"x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]),
"x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]),
"x86_64-unknown-linux-gnu" => {
common_libs("linux", "x86_64", &["asan", "dfsan", "lsan", "msan", "safestack", "tsan"])
}
"x86_64-unknown-linux-gnu" => common_libs(
"linux",
"x86_64",
&["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan"],
),
"x86_64-unknown-linux-musl" => {
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
}

View file

@ -45,7 +45,7 @@ implementation:
[marked][sanitizer-attribute] with appropriate LLVM attribute:
`SanitizeAddress`, `SanitizeHWAddress`, `SanitizeMemory`, or
`SanitizeThread`. By default all functions are instrumented, but this
behaviour can be changed with `#[sanitize(xyz = "on|off")]`.
behaviour can be changed with `#[sanitize(xyz = "on|off|<other>")]`.
* The decision whether to perform instrumentation or not is possible only at a
function granularity. In the cases were those decision differ between

View file

@ -174,6 +174,7 @@ pub enum Sanitizer {
ShadowCallStack,
Thread,
Hwaddress,
Realtime,
}
#[derive(Clone, Copy, Debug, PartialEq)]

View file

@ -165,6 +165,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"needs-sanitizer-leak",
"needs-sanitizer-memory",
"needs-sanitizer-memtag",
"needs-sanitizer-realtime",
"needs-sanitizer-safestack",
"needs-sanitizer-shadow-call-stack",
"needs-sanitizer-support",

View file

@ -69,6 +69,11 @@ pub(super) fn handle_needs(
condition: cache.sanitizer_memtag,
ignore_reason: "ignored on targets without memory tagging sanitizer",
},
Need {
name: "needs-sanitizer-realtime",
condition: cache.sanitizer_realtime,
ignore_reason: "ignored on targets without realtime sanitizer",
},
Need {
name: "needs-sanitizer-shadow-call-stack",
condition: cache.sanitizer_shadow_call_stack,
@ -320,6 +325,7 @@ pub(super) struct CachedNeedsConditions {
sanitizer_thread: bool,
sanitizer_hwaddress: bool,
sanitizer_memtag: bool,
sanitizer_realtime: bool,
sanitizer_shadow_call_stack: bool,
sanitizer_safestack: bool,
xray: bool,
@ -346,6 +352,7 @@ impl CachedNeedsConditions {
sanitizer_thread: sanitizers.contains(&Sanitizer::Thread),
sanitizer_hwaddress: sanitizers.contains(&Sanitizer::Hwaddress),
sanitizer_memtag: sanitizers.contains(&Sanitizer::Memtag),
sanitizer_realtime: sanitizers.contains(&Sanitizer::Realtime),
sanitizer_shadow_call_stack: sanitizers.contains(&Sanitizer::ShadowCallStack),
sanitizer_safestack: sanitizers.contains(&Sanitizer::Safestack),
xray: config.target_cfg().xray,

View file

@ -513,7 +513,7 @@ LL | #[sanitize(hwaddress = "on|off")]
| ++++++++++++++++++++++
LL | #[sanitize(kcfi = "on|off")]
| +++++++++++++++++
= and 5 other candidates
= and 6 other candidates
error[E0565]: malformed `no_implicit_prelude` attribute input
--> $DIR/malformed-attrs.rs:101:1

View file

@ -120,7 +120,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | sanitize = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, and `thread`
= note: expected values for `sanitize` are: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `realtime`, `safestack`, `shadow-call-stack`, and `thread`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`

View file

@ -19,3 +19,6 @@ fn name_value() {}
#[sanitize] //~ ERROR malformed `sanitize` attribute input
fn just_word() {}
#[sanitize(realtime = "on")] //~ ERROR malformed `sanitize` attribute input
fn wrong_value_realtime() {}

View file

@ -4,7 +4,7 @@ error[E0539]: malformed `sanitize` attribute input
LL | #[sanitize(brontosaurus = "off")]
| ^^^^^^^^^^^------------^^^^^^^^^^
| |
| valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread" or "hwaddress"
| valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread", "hwaddress" or "realtime"
|
help: try changing it to one of the following valid forms of the attribute
|
@ -20,7 +20,7 @@ LL + #[sanitize(hwaddress = "on|off")]
LL - #[sanitize(brontosaurus = "off")]
LL + #[sanitize(kcfi = "on|off")]
|
= and 5 other candidates
= and 6 other candidates
error: multiple `sanitize` attributes
--> $DIR/invalid-sanitize.rs:6:1
@ -68,7 +68,7 @@ LL + #[sanitize(hwaddress = "on|off")]
LL - #[sanitize(address = "bogus")]
LL + #[sanitize(kcfi = "on|off")]
|
= and 5 other candidates
= and 6 other candidates
error[E0539]: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:17:1
@ -90,7 +90,7 @@ LL + #[sanitize(hwaddress = "on|off")]
LL - #[sanitize = "off"]
LL + #[sanitize(kcfi = "on|off")]
|
= and 5 other candidates
= and 6 other candidates
error[E0539]: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:20:1
@ -108,8 +108,32 @@ LL | #[sanitize(hwaddress = "on|off")]
| ++++++++++++++++++++++
LL | #[sanitize(kcfi = "on|off")]
| +++++++++++++++++
= and 5 other candidates
= and 6 other candidates
error: aborting due to 6 previous errors
error[E0539]: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:23:1
|
LL | #[sanitize(realtime = "on")]
| ^^^^^^^^^^^^^^^^^^^^^^----^^
| |
| valid arguments are "nonblocking", "blocking" or "caller"
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[sanitize(realtime = "on")]
LL + #[sanitize(address = "on|off")]
|
LL - #[sanitize(realtime = "on")]
LL + #[sanitize(cfi = "on|off")]
|
LL - #[sanitize(realtime = "on")]
LL + #[sanitize(hwaddress = "on|off")]
|
LL - #[sanitize(realtime = "on")]
LL + #[sanitize(kcfi = "on|off")]
|
= and 6 other candidates
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0539`.

View file

@ -0,0 +1,20 @@
//@ needs-sanitizer-support
//@ needs-sanitizer-realtime
//
//@ compile-flags: -Z sanitizer=realtime
//@ exec-env: RTSAN_OPTIONS=abort_on_error=0
//
//@ run-fail
//@ error-pattern: Intercepted call to real-time unsafe function `malloc` in real-time context!
//@ ignore-backends: gcc
#![feature(sanitize)]
#[sanitize(realtime = "nonblocking")]
fn sanitizer_on() {
let mut vec = vec![0, 1, 2];
println!("alloc not detected");
}
fn main() {
sanitizer_on();
}

View file

@ -0,0 +1,25 @@
//@ needs-sanitizer-support
//@ needs-sanitizer-realtime
//
//@ compile-flags: -Z sanitizer=realtime
//@ exec-env: RTSAN_OPTIONS=abort_on_error=0
//
//@ run-fail
//@ error-pattern: Call to blocking function
//@ error-pattern: realtime_blocking::blocking::
//@ ignore-backends: gcc
#![feature(sanitize)]
#[sanitize(realtime = "nonblocking")]
fn sanitizer_on() {
blocking();
}
#[sanitize(realtime = "blocking")]
fn blocking() {
println!("blocking call not detected");
}
fn main() {
sanitizer_on();
}

View file

@ -0,0 +1,28 @@
//@ needs-sanitizer-support
//@ needs-sanitizer-realtime
//
//@ compile-flags: -Z sanitizer=realtime
//@ exec-env: RTSAN_OPTIONS=abort_on_error=0
//
//@ run-fail
//@ error-pattern: RealtimeSanitizer: blocking-call
//@ ignore-backends: gcc
#![feature(sanitize)]
#[sanitize(realtime = "nonblocking")]
fn sanitizer_on() {
caller();
}
fn caller() {
blocking()
}
#[sanitize(realtime = "blocking")]
fn blocking() {
println!("blocking call not detected");
}
fn main() {
sanitizer_on();
}