File tree 3 files changed +62
-1
lines changed
kani-compiler/src/kani_middle/transform 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> {
440
440
// The write bytes intrinsic may trigger UB in safe code.
441
441
// pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize)
442
442
// <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
+ ) ;
444
450
let TyKind :: RigidTy ( RigidTy :: RawPtr ( target_ty, Mutability :: Mut ) ) =
445
451
args[ 0 ] . ty ( self . locals ) . unwrap ( ) . kind ( )
446
452
else {
@@ -449,6 +455,19 @@ impl<'a> MirVisitor for CheckValueVisitor<'a> {
449
455
let validity = ty_validity_per_offset ( & self . machine , target_ty, 0 ) ;
450
456
match validity {
451
457
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
+ }
452
471
_ => self . push_target ( SourceOp :: UnsupportedCheck {
453
472
check : "write_bytes" . to_string ( ) ,
454
473
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