@@ -419,7 +419,7 @@ struct MemoryChunkIterator<'a> {
419
419
// exclusive end index (start + len, so one past the last valid address)
420
420
vm_addr_end : u64 ,
421
421
len : u64 ,
422
- account_index : usize ,
422
+ account_index : Option < usize > ,
423
423
is_account : Option < bool > ,
424
424
}
425
425
@@ -446,7 +446,7 @@ impl<'a> MemoryChunkIterator<'a> {
446
446
len,
447
447
vm_addr_start : vm_addr,
448
448
vm_addr_end,
449
- account_index : 0 ,
449
+ account_index : None ,
450
450
is_account : None ,
451
451
} )
452
452
}
@@ -490,14 +490,18 @@ impl<'a> Iterator for MemoryChunkIterator<'a> {
490
490
491
491
let region_is_account;
492
492
493
+ let mut account_index = self . account_index . unwrap_or_default ( ) ;
494
+ self . account_index = Some ( account_index) ;
495
+
493
496
loop {
494
- if let Some ( account) = self . accounts . get ( self . account_index ) {
497
+ if let Some ( account) = self . accounts . get ( account_index) {
495
498
let account_addr = account. vm_data_addr ;
496
499
let resize_addr = account_addr. saturating_add ( account. original_data_len as u64 ) ;
497
500
498
501
if resize_addr < region. vm_addr {
499
502
// region is after this account, move on next one
500
- self . account_index = self . account_index . saturating_add ( 1 ) ;
503
+ account_index = account_index. saturating_add ( 1 ) ;
504
+ self . account_index = Some ( account_index) ;
501
505
} else {
502
506
region_is_account =
503
507
region. vm_addr == account_addr || region. vm_addr == resize_addr;
@@ -550,6 +554,41 @@ impl DoubleEndedIterator for MemoryChunkIterator<'_> {
550
554
}
551
555
} ;
552
556
557
+ let region_is_account;
558
+
559
+ let mut account_index = self
560
+ . account_index
561
+ . unwrap_or_else ( || self . accounts . len ( ) . saturating_sub ( 1 ) ) ;
562
+ self . account_index = Some ( account_index) ;
563
+
564
+ loop {
565
+ let Some ( account) = self . accounts . get ( account_index) else {
566
+ // address is after all the accounts
567
+ region_is_account = false ;
568
+ break ;
569
+ } ;
570
+
571
+ let account_addr = account. vm_data_addr ;
572
+ let resize_addr = account_addr. saturating_add ( account. original_data_len as u64 ) ;
573
+
574
+ if account_index > 0 && account_addr > region. vm_addr {
575
+ account_index = account_index. saturating_sub ( 1 ) ;
576
+
577
+ self . account_index = Some ( account_index) ;
578
+ } else {
579
+ region_is_account = region. vm_addr == account_addr || region. vm_addr == resize_addr;
580
+ break ;
581
+ }
582
+ }
583
+
584
+ if let Some ( is_account) = self . is_account {
585
+ if is_account != region_is_account {
586
+ return Some ( Err ( SyscallError :: InvalidLength . into ( ) ) ) ;
587
+ }
588
+ } else {
589
+ self . is_account = Some ( region_is_account) ;
590
+ }
591
+
553
592
let chunk_len = if region. vm_addr >= self . vm_addr_start {
554
593
// consume the whole region
555
594
let len = self . vm_addr_end . saturating_sub ( region. vm_addr ) ;
0 commit comments