@@ -63,16 +63,23 @@ where
63
63
T : ?Sized ,
64
64
<T as Pointee >:: Metadata : PtrProperties < T > ,
65
65
{
66
+ // The interface takes a mutable pointer to improve readability of the signature.
67
+ // However, using constant pointer avoid unnecessary instrumentation, and it is as powerful.
68
+ // Hence, cast to `*const T`.
69
+ let ptr: * const T = ptr;
66
70
let ( thin_ptr, metadata) = ptr. to_raw_parts ( ) ;
67
71
metadata. is_ptr_aligned ( thin_ptr, Internal ) && is_inbounds ( & metadata, thin_ptr)
68
72
}
69
73
70
- /// Assert that the pointer is valid for access according to [crate::mem] conditions 1, 2 and 3.
74
+ /// Check if the pointer is valid for unaligned write access according to [crate::mem] conditions
75
+ /// 1, 2 and 3.
71
76
///
72
77
/// Note this function succeeds for unaligned pointers. See [self::can_write] if you also
73
78
/// want to check pointer alignment.
74
79
///
75
- /// This function will either panic or return `true`. This is to make it easier to use it in
80
+ /// This function will panic today if the pointer is not null, and it points to an unallocated or
81
+ /// deallocated memory location. This is an existing Kani limitation.
82
+ /// See <https://github.com/model-checking/kani/issues/2690> for more details.
76
83
#[ crate :: unstable(
77
84
feature = "mem-predicates" ,
78
85
issue = 2690 ,
96
103
/// TODO: Kani should automatically add those checks when a de-reference happens.
97
104
/// <https://github.com/model-checking/kani/issues/2975>
98
105
///
99
- /// Invoking this with an invalid pointer will panic due to a memory violation error.
106
+ /// This function will panic today if the pointer is not null, and it points to an unallocated or
107
+ /// deallocated memory location. This is an existing Kani limitation.
108
+ /// See <https://github.com/model-checking/kani/issues/2690> for more details.
100
109
#[ crate :: unstable(
101
110
feature = "mem-predicates" ,
102
111
issue = 2690 ,
@@ -114,6 +123,33 @@ where
114
123
&& unsafe { has_valid_value ( ptr) }
115
124
}
116
125
126
+ /// Checks that pointer `ptr` point to a valid value of type `T`.
127
+ ///
128
+ /// For that, the pointer has to be a valid pointer according to [crate::mem] conditions 1, 2
129
+ /// and 3,
130
+ /// and the value stored must respect the validity invariants for type `T`.
131
+ ///
132
+ /// Note this function succeeds for unaligned pointers. See [self::can_dereference] if you also
133
+ /// want to check pointer alignment.
134
+ ///
135
+ /// This function will panic today if the pointer is not null, and it points to an unallocated or
136
+ /// deallocated memory location. This is an existing Kani limitation.
137
+ /// See <https://github.com/model-checking/kani/issues/2690> for more details.
138
+ #[ crate :: unstable(
139
+ feature = "mem-predicates" ,
140
+ issue = 2690 ,
141
+ reason = "experimental memory predicate API"
142
+ ) ]
143
+ #[ allow( clippy:: not_unsafe_ptr_arg_deref) ]
144
+ pub fn can_read_unaligned < T > ( ptr : * const T ) -> bool
145
+ where
146
+ T : ?Sized ,
147
+ <T as Pointee >:: Metadata : PtrProperties < T > ,
148
+ {
149
+ let ( thin_ptr, metadata) = ptr. to_raw_parts ( ) ;
150
+ is_inbounds ( & metadata, thin_ptr) && unsafe { has_valid_value ( ptr) }
151
+ }
152
+
117
153
/// Checks that `data_ptr` points to an allocation that can hold data of size calculated from `T`.
118
154
///
119
155
/// This will panic if `data_ptr` points to an invalid `non_null`
@@ -244,6 +280,10 @@ unsafe fn is_allocated(_ptr: *const (), _size: usize) -> bool {
244
280
}
245
281
246
282
/// Check if the value stored in the given location satisfies type `T` validity requirements.
283
+ ///
284
+ /// # Safety
285
+ ///
286
+ /// - Users have to ensure that the pointer is aligned the pointed memory is allocated.
247
287
#[ rustc_diagnostic_item = "KaniValidValue" ]
248
288
#[ inline( never) ]
249
289
unsafe fn has_valid_value < T : ?Sized > ( _ptr : * const T ) -> bool {
@@ -252,7 +292,7 @@ unsafe fn has_valid_value<T: ?Sized>(_ptr: *const T) -> bool {
252
292
253
293
#[ cfg( test) ]
254
294
mod tests {
255
- use super :: { can_write, PtrProperties } ;
295
+ use super :: { can_dereference , can_write, PtrProperties } ;
256
296
use crate :: mem:: private:: Internal ;
257
297
use std:: fmt:: Debug ;
258
298
use std:: intrinsics:: size_of;
@@ -306,39 +346,42 @@ mod tests {
306
346
307
347
#[ test]
308
348
pub fn test_empty_slice ( ) {
309
- let slice_ptr = Vec :: < char > :: new ( ) . as_slice ( ) as * const [ char ] ;
310
- can_write ( slice_ptr) ;
349
+ let slice_ptr = Vec :: < char > :: new ( ) . as_mut_slice ( ) as * mut [ char ] ;
350
+ assert ! ( can_write( slice_ptr) ) ;
311
351
}
312
352
313
353
#[ test]
314
354
pub fn test_empty_str ( ) {
315
- let slice_ptr = String :: new ( ) . as_str ( ) as * const str ;
316
- can_write ( slice_ptr) ;
355
+ let slice_ptr = String :: new ( ) . as_mut_str ( ) as * mut str ;
356
+ assert ! ( can_write( slice_ptr) ) ;
317
357
}
318
358
319
359
#[ test]
320
360
fn test_dangling_zst ( ) {
321
- test_dangling_of_t :: < ( ) > ( ) ;
322
- test_dangling_of_t :: < [ ( ) ; 10 ] > ( ) ;
361
+ test_dangling_of_zst :: < ( ) > ( ) ;
362
+ test_dangling_of_zst :: < [ ( ) ; 10 ] > ( ) ;
323
363
}
324
364
325
- fn test_dangling_of_t < T > ( ) {
326
- let dangling: * const T = NonNull :: < T > :: dangling ( ) . as_ptr ( ) ;
327
- can_write ( dangling) ;
365
+ fn test_dangling_of_zst < T > ( ) {
366
+ let dangling: * mut T = NonNull :: < T > :: dangling ( ) . as_ptr ( ) ;
367
+ assert ! ( can_write( dangling) ) ;
328
368
329
- let vec_ptr = Vec :: < T > :: new ( ) . as_ptr ( ) ;
330
- can_write ( vec_ptr) ;
369
+ let vec_ptr = Vec :: < T > :: new ( ) . as_mut_ptr ( ) ;
370
+ assert ! ( can_write( vec_ptr) ) ;
331
371
}
332
372
333
373
#[ test]
334
- #[ should_panic( expected = "Expected valid pointer, but found `null`" ) ]
335
374
fn test_null_fat_ptr ( ) {
336
- can_write ( ptr:: null :: < char > ( ) as * const dyn Debug ) ;
375
+ assert ! ( !can_dereference ( ptr:: null:: <char >( ) as * const dyn Debug ) ) ;
337
376
}
338
377
339
378
#[ test]
340
- #[ should_panic( expected = "Expected valid pointer, but found `null`" ) ]
341
379
fn test_null_char ( ) {
342
- can_write ( ptr:: null :: < char > ( ) ) ;
380
+ assert ! ( !can_dereference( ptr:: null:: <char >( ) ) ) ;
381
+ }
382
+
383
+ #[ test]
384
+ fn test_null_mut ( ) {
385
+ assert ! ( !can_write( ptr:: null_mut:: <String >( ) ) ) ;
343
386
}
344
387
}
0 commit comments