File tree Expand file tree Collapse file tree 3 files changed +62
-1
lines changed
kani-compiler/src/kani_middle/transform Expand file tree Collapse file tree 3 files changed +62
-1
lines changed Original file line number Diff line number Diff line change @@ -440,7 +440,13 @@ impl<'a> MirVisitor for CheckValueVisitor<'a> {
440440 // The write bytes intrinsic may trigger UB in safe code.
441441 // pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize)
442442 // <https://doc.rust-lang.org/stable/core/intrinsics/fn.write_bytes.html>
443- // We don't support this operation yet.
443+ // This is an over-approximation since writing an invalid value is
444+ // not UB, only reading it will be.
445+ assert_eq ! (
446+ args. len( ) ,
447+ 3 ,
448+ "Unexpected number of arguments for `write_bytes`"
449+ ) ;
444450 let TyKind :: RigidTy ( RigidTy :: RawPtr ( target_ty, Mutability :: Mut ) ) =
445451 args[ 0 ] . ty ( self . locals ) . unwrap ( ) . kind ( )
446452 else {
@@ -449,6 +455,19 @@ impl<'a> MirVisitor for CheckValueVisitor<'a> {
449455 let validity = ty_validity_per_offset ( & self . machine , target_ty, 0 ) ;
450456 match validity {
451457 Ok ( ranges) if ranges. is_empty ( ) => { }
458+ Ok ( ranges) => {
459+ let sz = Const :: try_from_uint (
460+ target_ty. layout ( ) . unwrap ( ) . shape ( ) . size . bytes ( )
461+ as u128 ,
462+ UintTy :: Usize ,
463+ )
464+ . unwrap ( ) ;
465+ self . push_target ( SourceOp :: BytesValidity {
466+ target_ty,
467+ rvalue : Rvalue :: Repeat ( args[ 1 ] . clone ( ) , sz) ,
468+ ranges,
469+ } )
470+ }
452471 _ => self . push_target ( SourceOp :: UnsupportedCheck {
453472 check : "write_bytes" . to_string ( ) ,
454473 ty : target_ty,
Original file line number Diff line number Diff line change 1+ // Copyright Kani Contributors
2+ // SPDX-License-Identifier: Apache-2.0 OR MIT
3+ // kani-flags: -Z valid-value-checks
4+ //! Check that Kani can identify UB when converting from a maybe uninit().
5+
6+ use std:: mem:: MaybeUninit ;
7+ use std:: num:: NonZeroI64 ;
8+
9+ #[ kani:: proof]
10+ pub fn check_valid_zeroed ( ) {
11+ let maybe = MaybeUninit :: zeroed ( ) ;
12+ let val: u128 = unsafe { maybe. assume_init ( ) } ;
13+ assert_eq ! ( val, 0 ) ;
14+ }
15+
16+ #[ kani:: proof]
17+ #[ kani:: should_panic]
18+ pub fn check_invalid_zeroed ( ) {
19+ let maybe = MaybeUninit :: zeroed ( ) ;
20+ let _val: NonZeroI64 = unsafe { maybe. assume_init ( ) } ;
21+ }
Original file line number Diff line number Diff line change 1+ // Copyright Kani Contributors
2+ // SPDX-License-Identifier: Apache-2.0 OR MIT
3+ // kani-flags: -Z valid-value-checks
4+ //! Check that Kani can identify UB when using write_bytes for initializing a variable.
5+ #![ feature( core_intrinsics) ]
6+
7+ #[ kani:: proof]
8+ #[ kani:: should_panic]
9+ pub fn check_invalid_write ( ) {
10+ let mut val = 'a' ;
11+ let ptr = & mut val as * mut char ;
12+ // Should fail given that we wrote invalid value to array of char.
13+ unsafe { std:: intrinsics:: write_bytes ( ptr, kani:: any ( ) , 1 ) } ;
14+ }
15+
16+ #[ kani:: proof]
17+ pub fn check_valid_write ( ) {
18+ let mut val = 10u128 ;
19+ let ptr = & mut val as * mut _ ;
20+ unsafe { std:: intrinsics:: write_bytes ( ptr, kani:: any ( ) , 1 ) } ;
21+ }
You can’t perform that action at this time.
0 commit comments