// Verifies that the `#[sanitize(address = "off")]` attribute can be used to // selectively disable sanitizer instrumentation. // //@ needs-sanitizer-address //@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0 #![crate_type = "lib"] #![feature(sanitize)] // CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address // CHECK-NOT: @__asan_global_SANITIZED #[no_mangle] #[sanitize(address = "off")] pub static UNSANITIZED: u32 = 0; // CHECK: @__asan_global_SANITIZED #[no_mangle] pub static SANITIZED: u32 = 0; // CHECK-LABEL: ; sanitize_off::unsanitized // CHECK-NEXT: ; Function Attrs: // CHECK-NOT: sanitize_address // CHECK: start: // CHECK-NOT: call void @__asan_report_load // CHECK: } #[sanitize(address = "off")] pub fn unsanitized(b: &mut u8) -> u8 { *b } // CHECK-LABEL: ; sanitize_off::sanitized // CHECK-NEXT: ; Function Attrs: // CHECK: sanitize_address // CHECK: start: // CHECK: call void @__asan_report_load // CHECK: } pub fn sanitized(b: &mut u8) -> u8 { *b } #[sanitize(address = "off")] pub mod foo { // CHECK-LABEL: ; sanitize_off::foo::unsanitized // CHECK-NEXT: ; Function Attrs: // CHECK-NOT: sanitize_address // CHECK: start: // CHECK-NOT: call void @__asan_report_load // CHECK: } pub fn unsanitized(b: &mut u8) -> u8 { *b } // CHECK-LABEL: ; sanitize_off::foo::sanitized // CHECK-NEXT: ; Function Attrs: // CHECK: sanitize_address // CHECK: start: // CHECK: call void @__asan_report_load // CHECK: } #[sanitize(address = "on")] pub fn sanitized(b: &mut u8) -> u8 { *b } } pub trait MyTrait { fn unsanitized(&self, b: &mut u8) -> u8; fn sanitized(&self, b: &mut u8) -> u8; // CHECK-LABEL: ; sanitize_off::MyTrait::unsanitized_default // CHECK-NEXT: ; Function Attrs: // CHECK-NOT: sanitize_address // CHECK: start: // CHECK-NOT: call void @__asan_report_load // CHECK: } #[sanitize(address = "off")] fn unsanitized_default(&self, b: &mut u8) -> u8 { *b } // CHECK-LABEL: ; sanitize_off::MyTrait::sanitized_default // CHECK-NEXT: ; Function Attrs: // CHECK: sanitize_address // CHECK: start: // CHECK: call void @__asan_report_load // CHECK: } fn sanitized_default(&self, b: &mut u8) -> u8 { *b } } #[sanitize(address = "off")] impl MyTrait for () { // CHECK-LABEL: ; <() as sanitize_off::MyTrait>::unsanitized // CHECK-NEXT: ; Function Attrs: // CHECK-NOT: sanitize_address // CHECK: start: // CHECK-NOT: call void @__asan_report_load // CHECK: } fn unsanitized(&self, b: &mut u8) -> u8 { *b } // CHECK-LABEL: ; <() as sanitize_off::MyTrait>::sanitized // CHECK-NEXT: ; Function Attrs: // CHECK: sanitize_address // CHECK: start: // CHECK: call void @__asan_report_load // CHECK: } #[sanitize(address = "on")] fn sanitized(&self, b: &mut u8) -> u8 { *b } } pub fn expose_trait(b: &mut u8) -> u8 { <() as MyTrait>::unsanitized_default(&(), b); <() as MyTrait>::sanitized_default(&(), b) } #[sanitize(address = "off")] pub mod outer { #[sanitize(thread = "off")] pub mod inner { // CHECK-LABEL: ; sanitize_off::outer::inner::unsanitized // CHECK-NEXT: ; Function Attrs: // CHECK-NOT: sanitize_address // CHECK: start: // CHECK-NOT: call void @__asan_report_load // CHECK: } pub fn unsanitized() { let xs = [0, 1, 2, 3]; // Avoid optimizing everything out. let xs = std::hint::black_box(xs.as_ptr()); let code = unsafe { *xs.offset(4) }; std::process::exit(code); } } }