@@ -109,6 +109,10 @@ pub trait VolatileMemory {
109109
110110 /// Returns a [`VolatileSlice`](struct.VolatileSlice.html) of `count` bytes starting at
111111 /// `offset`.
112+ ///
113+ /// Note that the property `get_slice(offset, count).len() == count` MUST NOT be
114+ /// relied on for the correctness of unsafe code. This is a safe function inside of a
115+ /// safe trait, and implementors are under no obligation to follow its documentation.
112116 fn get_slice ( & self , offset : usize , count : usize ) -> Result < VolatileSlice < BS < Self :: B > > > ;
113117
114118 /// Gets a slice of memory for the entire region that supports volatile access.
@@ -119,8 +123,18 @@ pub trait VolatileMemory {
119123 /// Gets a `VolatileRef` at `offset`.
120124 fn get_ref < T : ByteValued > ( & self , offset : usize ) -> Result < VolatileRef < T , BS < Self :: B > > > {
121125 let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
122- // SAFETY: This is safe because the pointer is range-checked by get_slice, and
123- // the lifetime is the same as self.
126+
127+ assert_eq ! (
128+ slice. len( ) ,
129+ size_of:: <T >( ) ,
130+ "VolatileMemory::get_slice(offset, count) returned slice of length != count."
131+ ) ;
132+
133+ // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
134+ // slice.addr is valid memory of size slice.len(). The assert above ensures that
135+ // the length of the slice is exactly enough to hold one `T`. Lastly, the lifetime of the
136+ // returned VolatileRef match that of the VolatileSlice returned by get_slice and thus the
137+ // lifetime one `self`.
124138 unsafe {
125139 Ok ( VolatileRef :: with_bitmap (
126140 slice. addr ,
@@ -146,8 +160,18 @@ pub trait VolatileMemory {
146160 size : size_of :: < T > ( ) ,
147161 } ) ?;
148162 let slice = self . get_slice ( offset, nbytes as usize ) ?;
149- // SAFETY: This is safe because the pointer is range-checked by get_slice, and
150- // the lifetime is the same as self.
163+
164+ assert_eq ! (
165+ slice. len( ) ,
166+ nbytes as usize ,
167+ "VolatileMemory::get_slice(offset, count) returned slice of length != count."
168+ ) ;
169+
170+ // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
171+ // slice.addr is valid memory of size slice.len(). The assert above ensures that
172+ // the length of the slice is exactly enough to hold `n` instances of `T`. Lastly, the lifetime of the
173+ // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
174+ // lifetime one `self`.
151175 unsafe {
152176 Ok ( VolatileArrayRef :: with_bitmap (
153177 slice. addr ,
@@ -171,7 +195,21 @@ pub trait VolatileMemory {
171195 unsafe fn aligned_as_ref < T : ByteValued > ( & self , offset : usize ) -> Result < & T > {
172196 let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
173197 slice. check_alignment ( align_of :: < T > ( ) ) ?;
174- Ok ( & * ( slice. addr as * const T ) )
198+
199+ assert_eq ! (
200+ slice. len( ) ,
201+ size_of:: <T >( ) ,
202+ "VolatileMemory::get_slice(offset, count) returned slice of length != count."
203+ ) ;
204+
205+ // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
206+ // slice.addr is valid memory of size slice.len(). The assert above ensures that
207+ // the length of the slice is exactly enough to hold one `T`.
208+ // Dereferencing the pointer is safe because we check the alignment above, and the invariants
209+ // of this function ensure that no aliasing pointers exist. Lastly, the lifetime of the
210+ // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
211+ // lifetime one `self`.
212+ unsafe { Ok ( & * ( slice. addr as * const T ) ) }
175213 }
176214
177215 /// Returns a mutable reference to an instance of `T` at `offset`. Mutable accesses performed
@@ -191,7 +229,21 @@ pub trait VolatileMemory {
191229 let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
192230 slice. check_alignment ( align_of :: < T > ( ) ) ?;
193231
194- Ok ( & mut * ( slice. addr as * mut T ) )
232+ assert_eq ! (
233+ slice. len( ) ,
234+ size_of:: <T >( ) ,
235+ "VolatileMemory::get_slice(offset, count) returned slice of length != count."
236+ ) ;
237+
238+ // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
239+ // slice.addr is valid memory of size slice.len(). The assert above ensures that
240+ // the length of the slice is exactly enough to hold one `T`.
241+ // Dereferencing the pointer is safe because we check the alignment above, and the invariants
242+ // of this function ensure that no aliasing pointers exist. Lastly, the lifetime of the
243+ // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
244+ // lifetime one `self`.
245+
246+ unsafe { Ok ( & mut * ( slice. addr as * mut T ) ) }
195247 }
196248
197249 /// Returns a reference to an instance of `T` at `offset`. Mutable accesses performed
@@ -206,8 +258,18 @@ pub trait VolatileMemory {
206258 let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
207259 slice. check_alignment ( align_of :: < T > ( ) ) ?;
208260
209- // SAFETY: This is safe because the pointer is range-checked by get_slice, and
210- // the lifetime is the same as self.
261+ assert_eq ! (
262+ slice. len( ) ,
263+ size_of:: <T >( ) ,
264+ "VolatileMemory::get_slice(offset, count) returned slice of length != count."
265+ ) ;
266+
267+ // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
268+ // slice.addr is valid memory of size slice.len(). The assert above ensures that
269+ // the length of the slice is exactly enough to hold one `T`.
270+ // Dereferencing the pointer is safe because we check the alignment above. Lastly, the lifetime of the
271+ // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
272+ // lifetime one `self`.
211273 unsafe { Ok ( & * ( slice. addr as * const T ) ) }
212274 }
213275
0 commit comments