@@ -366,29 +366,59 @@ impl<T: candid::CandidType + serde::de::DeserializeOwned, M: Memory> Storage<T,
366366 /// Reads the persistent state from stable memory just outside of the space allocated to the highest user number.
367367 /// This is only used to restore state in `post_upgrade`.
368368 pub fn read_persistent_state ( & self ) -> Result < PersistentState , PersistentStateError > {
369+ const WASM_PAGE_SIZE : u64 = 65536 ;
369370 let address = self . unused_memory_start ( ) ;
370- let mut reader = Reader :: new ( & self . memory , address) ;
371371
372+ if address > self . memory . size ( ) * WASM_PAGE_SIZE {
373+ // the address where the persistent state would be is not allocated yet
374+ return Err ( PersistentStateError :: NotFound ) ;
375+ }
376+
377+ let mut reader = Reader :: new ( & self . memory , address) ;
372378 let mut magic_buf: [ u8 ; 4 ] = [ 0 ; 4 ] ;
373- reader
379+ let bytes_read = reader
374380 . read ( & mut magic_buf)
375- . map_err ( |err| PersistentStateError :: ReadError ( err) ) ?;
381+ // if we hit out of bounds here, this means that the persistent state has not been
382+ // written at the expected location and thus cannot be found
383+ . map_err ( |_| PersistentStateError :: NotFound ) ?;
376384
377- if magic_buf != PERSISTENT_STATE_MAGIC {
385+ if bytes_read != 4 || magic_buf != PERSISTENT_STATE_MAGIC {
386+ // less than the expected number of bytes were read or the magic does not match
387+ // --> this is not the persistent state
378388 return Err ( PersistentStateError :: NotFound ) ;
379389 }
380390
381391 let mut size_buf: [ u8 ; 8 ] = [ 0 ; 8 ] ;
382- reader
392+ let bytes_read = reader
383393 . read ( & mut size_buf)
384- . map_err ( |err| PersistentStateError :: ReadError ( err) ) ?;
394+ . map_err ( |err| PersistentStateError :: ReadError ( err) ) ? as u64 ;
395+
396+ // check if we actually read the required amount of data
397+ // note: this will only happen if we hit the memory bounds during read
398+ if bytes_read != 8 {
399+ let max_address = address + 4 + bytes_read;
400+ return Err ( PersistentStateError :: ReadError ( OutOfBounds {
401+ max_address,
402+ attempted_read_address : max_address + 1 ,
403+ } ) ) ;
404+ }
385405
386406 let size = u64:: from_le_bytes ( size_buf) ;
387407 let mut data_buf = Vec :: new ( ) ;
388408 data_buf. resize ( size as usize , 0 ) ;
389- reader
409+ let bytes_read = reader
390410 . read ( data_buf. as_mut_slice ( ) )
391- . map_err ( |err| PersistentStateError :: ReadError ( err) ) ?;
411+ . map_err ( |err| PersistentStateError :: ReadError ( err) ) ? as u64 ;
412+
413+ // check if we actually read the required amount of data
414+ // note: this will only happen if we hit the memory bounds during read
415+ if bytes_read != size {
416+ let max_address = address + 4 + 8 + bytes_read;
417+ return Err ( PersistentStateError :: ReadError ( OutOfBounds {
418+ max_address,
419+ attempted_read_address : max_address + 1 ,
420+ } ) ) ;
421+ }
392422
393423 candid:: decode_one ( & data_buf) . map_err ( |err| PersistentStateError :: CandidError ( err) )
394424 }
0 commit comments