@@ -109,6 +109,10 @@ pub trait VolatileMemory {
109
109
110
110
/// Returns a [`VolatileSlice`](struct.VolatileSlice.html) of `count` bytes starting at
111
111
/// `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.
112
116
fn get_slice ( & self , offset : usize , count : usize ) -> Result < VolatileSlice < BS < Self :: B > > > ;
113
117
114
118
/// Gets a slice of memory for the entire region that supports volatile access.
@@ -119,8 +123,18 @@ pub trait VolatileMemory {
119
123
/// Gets a `VolatileRef` at `offset`.
120
124
fn get_ref < T : ByteValued > ( & self , offset : usize ) -> Result < VolatileRef < T , BS < Self :: B > > > {
121
125
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`.
124
138
unsafe {
125
139
Ok ( VolatileRef :: with_bitmap (
126
140
slice. addr ,
@@ -146,8 +160,18 @@ pub trait VolatileMemory {
146
160
size : size_of :: < T > ( ) ,
147
161
} ) ?;
148
162
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`.
151
175
unsafe {
152
176
Ok ( VolatileArrayRef :: with_bitmap (
153
177
slice. addr ,
@@ -171,7 +195,21 @@ pub trait VolatileMemory {
171
195
unsafe fn aligned_as_ref < T : ByteValued > ( & self , offset : usize ) -> Result < & T > {
172
196
let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
173
197
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 ) ) }
175
213
}
176
214
177
215
/// Returns a mutable reference to an instance of `T` at `offset`. Mutable accesses performed
@@ -191,7 +229,21 @@ pub trait VolatileMemory {
191
229
let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
192
230
slice. check_alignment ( align_of :: < T > ( ) ) ?;
193
231
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 ) ) }
195
247
}
196
248
197
249
/// Returns a reference to an instance of `T` at `offset`. Mutable accesses performed
@@ -206,8 +258,18 @@ pub trait VolatileMemory {
206
258
let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
207
259
slice. check_alignment ( align_of :: < T > ( ) ) ?;
208
260
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`.
211
273
unsafe { Ok ( & * ( slice. addr as * const T ) ) }
212
274
}
213
275
0 commit comments