@@ -630,7 +630,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
630630        range :  AllocRange , 
631631    )  -> & mut  [ u8 ]  { 
632632        self . mark_init ( range,  true ) ; 
633-         self . provenance . clear ( range,  cx) ; 
633+         self . provenance . clear ( range,  & self . bytes ,   cx) ; 
634634
635635        & mut  self . bytes [ range. start . bytes_usize ( ) ..range. end ( ) . bytes_usize ( ) ] 
636636    } 
@@ -643,7 +643,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
643643        range :  AllocRange , 
644644    )  -> * mut  [ u8 ]  { 
645645        self . mark_init ( range,  true ) ; 
646-         self . provenance . clear ( range,  cx) ; 
646+         self . provenance . clear ( range,  & self . bytes ,   cx) ; 
647647
648648        assert ! ( range. end( ) . bytes_usize( )  <= self . bytes. len( ) ) ;  // need to do our own bounds-check 
649649        // Crucially, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`. 
@@ -722,37 +722,49 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
722722            if  self . provenance . range_empty ( range,  cx)  { 
723723                return  Ok ( Scalar :: from_uint ( bits,  range. size ) ) ; 
724724            } 
725-             // If we get here, we have to check per-byte provenance, and join them together . 
725+             // If we get here, we have to check whether we can merge per-byte provenance . 
726726            let  prov = ' prov:  { 
727-                 if  !Prov :: OFFSET_IS_ADDR  { 
728-                     // FIXME(#146291): We need to ensure that we don't mix different pointers with 
729-                     // the same provenance. 
730-                     return  Err ( AllocError :: ReadPartialPointer ( range. start ) ) ; 
731-                 } 
732-                 // Initialize with first fragment. Must have index 0. 
733-                 let  Some ( ( mut  joint_prov,  0 ) )  = self . provenance . get_byte ( range. start ,  cx)  else  { 
727+                 // If there is any ptr-sized provenance overlapping with this range, 
728+                 // this is definitely mixing multiple pointers and we can bail. 
729+                 if  !self . provenance . range_ptrs_is_empty ( range,  cx)  { 
734730                    break  ' prov None ; 
735-                 } ; 
736-                 // Update with the remaining fragments. 
737-                 for  offset in  Size :: from_bytes ( 1 ) ..range. size  { 
738-                     // Ensure there is provenance here and it has the right index. 
739-                     let  Some ( ( frag_prov,  frag_idx) )  =
740-                         self . provenance . get_byte ( range. start  + offset,  cx) 
741-                     else  { 
731+                 } 
732+                 // Scan all fragments, and ensure their indices, provenance, and bytes match. 
733+                 // However, we have to ignore wildcard fragments for this (this is needed for Miri's 
734+                 // native-lib mode). Therefore, we will only know the expected provenance and bytes 
735+                 // once we find the first non-wildcard fragment. 
736+                 let  mut  expected = None ; 
737+                 for  idx in  Size :: ZERO ..range. size  { 
738+                     // Ensure there is provenance here. 
739+                     let  Some ( frag)  = self . provenance . get_byte ( range. start  + idx,  cx)  else  { 
742740                        break  ' prov None ; 
743741                    } ; 
744-                     // Wildcard provenance is allowed to come with any index (this is needed 
745-                     // for Miri's native-lib mode to work). 
746-                     if  u64:: from ( frag_idx)  != offset. bytes ( )  && Some ( frag_prov)  != Prov :: WILDCARD  { 
742+                     // If this is wildcard provenance, ignore this fragment. 
743+                     if  Some ( frag. prov )  == Prov :: WILDCARD  { 
744+                         continue ; 
745+                     } 
746+                     // For non-wildcard fragments, the index must match. 
747+                     if  u64:: from ( frag. idx )  != idx. bytes ( )  { 
747748                        break  ' prov None ; 
748749                    } 
749-                     // Merge this byte's provenance with the previous ones. 
750-                     joint_prov = match  Prov :: join ( joint_prov,  frag_prov)  { 
751-                         Some ( prov)  => prov, 
752-                         None  => break  ' prov None , 
753-                     } ; 
750+                     // If there are expectations registered, check them. 
751+                     // If not, record this fragment as setting the expectations. 
752+                     match  expected { 
753+                         Some ( expected)  => { 
754+                             if  ( frag. prov ,  frag. bytes )  != expected { 
755+                                 break  ' prov None ; 
756+                             } 
757+                         } 
758+                         None  => { 
759+                             expected = Some ( ( frag. prov ,  frag. bytes ) ) ; 
760+                         } 
761+                     } 
754762                } 
755-                 break  ' prov Some ( joint_prov) ; 
763+                 // The final provenance is the expected one we found along the way, or wildcard if 
764+                 // we didn't find any. 
765+                 break  ' prov Some ( 
766+                     expected. map ( |( prov,  _addr) | prov) . or_else ( || Prov :: WILDCARD ) . unwrap ( ) , 
767+                 ) ; 
756768            } ; 
757769            if  prov. is_none ( )  && !Prov :: OFFSET_IS_ADDR  { 
758770                // There are some bytes with provenance here but overall the provenance does not add up. 
@@ -816,7 +828,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
816828    /// Write "uninit" to the given memory range. 
817829pub  fn  write_uninit ( & mut  self ,  cx :  & impl  HasDataLayout ,  range :  AllocRange )  { 
818830        self . mark_init ( range,  false ) ; 
819-         self . provenance . clear ( range,  cx) ; 
831+         self . provenance . clear ( range,  & self . bytes ,   cx) ; 
820832    } 
821833
822834    /// Mark all bytes in the given range as initialised and reset the provenance 
@@ -831,21 +843,28 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
831843            size :  Size :: from_bytes ( self . len ( ) ) , 
832844        } ) ; 
833845        self . mark_init ( range,  true ) ; 
834-         self . provenance . write_wildcards ( cx,  range) ; 
846+         self . provenance . write_wildcards ( cx,  & self . bytes ,   range) ; 
835847    } 
836848
837849    /// Remove all provenance in the given memory range. 
838850pub  fn  clear_provenance ( & mut  self ,  cx :  & impl  HasDataLayout ,  range :  AllocRange )  { 
839-         self . provenance . clear ( range,  cx) ; 
851+         self . provenance . clear ( range,  & self . bytes ,   cx) ; 
840852    } 
841853
842854    pub  fn  provenance_merge_bytes ( & mut  self ,  cx :  & impl  HasDataLayout )  -> bool  { 
843855        self . provenance . merge_bytes ( cx) 
844856    } 
845857
858+     pub  fn  provenance_prepare_copy ( 
859+         & self , 
860+         range :  AllocRange , 
861+         cx :  & impl  HasDataLayout , 
862+     )  -> ProvenanceCopy < Prov >  { 
863+         self . provenance . prepare_copy ( range,  & self . bytes ,  cx) 
864+     } 
865+ 
846866    /// Applies a previously prepared provenance copy. 
847- /// The affected range, as defined in the parameters to `provenance().prepare_copy` is expected 
848- /// to be clear of provenance. 
867+ /// The affected range is expected to be clear of provenance. 
849868/// 
850869/// This is dangerous to use as it can violate internal `Allocation` invariants! 
851870/// It only exists to support an efficient implementation of `mem_copy_repeatedly`. 
0 commit comments