@@ -145,6 +145,27 @@ fn get_region(ctx: &Ctx, ptr: u32) -> CommunicationResult<Region> {
145
145
}
146
146
}
147
147
148
+ /// Performs plausibility checks in the given Region. Regions are always created by the
149
+ /// contract and this can be used to detect problems in the standard library of the contract.
150
+ fn validate_region ( region : & Region ) -> CommunicationResult < ( ) > {
151
+ if region. offset == 0 {
152
+ return Err ( CommunicationError :: zero_address ( ) ) ;
153
+ }
154
+ if region. length > region. capacity {
155
+ return Err ( CommunicationError :: region_length_exceeds_capacity (
156
+ region. length ,
157
+ region. capacity ,
158
+ ) ) ;
159
+ }
160
+ if region. capacity > ( u32:: MAX - region. offset ) {
161
+ return Err ( CommunicationError :: region_out_of_range (
162
+ region. offset ,
163
+ region. capacity ,
164
+ ) ) ;
165
+ }
166
+ Ok ( ( ) )
167
+ }
168
+
148
169
/// Overrides a Region at ptr in wasm memory with data
149
170
fn set_region ( ctx : & Ctx , ptr : u32 , data : Region ) -> CommunicationResult < ( ) > {
150
171
let memory = ctx. memory ( 0 ) ;
@@ -161,3 +182,119 @@ fn set_region(ctx: &Ctx, ptr: u32, data: Region) -> CommunicationResult<()> {
161
182
) ) ,
162
183
}
163
184
}
185
+
186
+ #[ cfg( test) ]
187
+ mod test {
188
+ use super :: * ;
189
+
190
+ #[ test]
191
+ fn validate_region_passes_for_valid_region ( ) {
192
+ // empty
193
+ let region = Region {
194
+ offset : 23 ,
195
+ capacity : 500 ,
196
+ length : 0 ,
197
+ } ;
198
+ validate_region ( & region) . unwrap ( ) ;
199
+
200
+ // half full
201
+ let region = Region {
202
+ offset : 23 ,
203
+ capacity : 500 ,
204
+ length : 250 ,
205
+ } ;
206
+ validate_region ( & region) . unwrap ( ) ;
207
+
208
+ // full
209
+ let region = Region {
210
+ offset : 23 ,
211
+ capacity : 500 ,
212
+ length : 500 ,
213
+ } ;
214
+ validate_region ( & region) . unwrap ( ) ;
215
+
216
+ // at end of linear memory (1)
217
+ let region = Region {
218
+ offset : u32:: MAX ,
219
+ capacity : 0 ,
220
+ length : 0 ,
221
+ } ;
222
+ validate_region ( & region) . unwrap ( ) ;
223
+
224
+ // at end of linear memory (2)
225
+ let region = Region {
226
+ offset : 1 ,
227
+ capacity : u32:: MAX - 1 ,
228
+ length : 0 ,
229
+ } ;
230
+ validate_region ( & region) . unwrap ( ) ;
231
+ }
232
+
233
+ #[ test]
234
+ fn validate_region_fails_for_zero_offset ( ) {
235
+ let region = Region {
236
+ offset : 0 ,
237
+ capacity : 500 ,
238
+ length : 250 ,
239
+ } ;
240
+ let result = validate_region ( & region) ;
241
+ match result. unwrap_err ( ) {
242
+ CommunicationError :: ZeroAddress { .. } => { }
243
+ e => panic ! ( "Got unexpected error: {:?}" , e) ,
244
+ }
245
+ }
246
+
247
+ #[ test]
248
+ fn validate_region_fails_for_length_exceeding_capacity ( ) {
249
+ let region = Region {
250
+ offset : 23 ,
251
+ capacity : 500 ,
252
+ length : 501 ,
253
+ } ;
254
+ let result = validate_region ( & region) ;
255
+ match result. unwrap_err ( ) {
256
+ CommunicationError :: RegionLengthExceedsCapacity {
257
+ length, capacity, ..
258
+ } => {
259
+ assert_eq ! ( length, 501 ) ;
260
+ assert_eq ! ( capacity, 500 ) ;
261
+ }
262
+ e => panic ! ( "Got unexpected error: {:?}" , e) ,
263
+ }
264
+ }
265
+
266
+ #[ test]
267
+ fn validate_region_fails_when_exceeding_address_space ( ) {
268
+ let region = Region {
269
+ offset : 23 ,
270
+ capacity : u32:: MAX ,
271
+ length : 501 ,
272
+ } ;
273
+ let result = validate_region ( & region) ;
274
+ match result. unwrap_err ( ) {
275
+ CommunicationError :: RegionOutOfRange {
276
+ offset, capacity, ..
277
+ } => {
278
+ assert_eq ! ( offset, 23 ) ;
279
+ assert_eq ! ( capacity, u32 :: MAX ) ;
280
+ }
281
+ e => panic ! ( "Got unexpected error: {:?}" , e) ,
282
+ }
283
+
284
+ let region = Region {
285
+ offset : u32:: MAX ,
286
+ capacity : 1 ,
287
+ length : 0 ,
288
+ } ;
289
+ let result = validate_region ( & region) ;
290
+ match result. unwrap_err ( ) {
291
+ CommunicationError :: RegionOutOfRange {
292
+ offset, capacity, ..
293
+ } => {
294
+ assert_eq ! ( offset, u32 :: MAX ) ;
295
+ assert_eq ! ( capacity, 1 ) ;
296
+ }
297
+ e => panic ! ( "Got unexpected error: {:?}" , e) ,
298
+ }
299
+ }
300
+ }
0 commit comments