@ -144,38 +144,67 @@ end
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					   meaningless  on  their  own .  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					module  AliasingDomain  =  AbstractDomain . Map  ( Var )  ( AbstractAddressDomain_JoinIsMin ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					(*  {3 Invalid addresses domain }  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					(* *  Attributes attached to addresses. This keeps track of which addresses are invalid, but is also 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					   used  by  models  for  bookkeeping .  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					module  AttributesDomain  :  sig 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  module  Attributes  :  AbstractDomain . S 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					(* *  Locations known to be invalid for some reason  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					module  InvalidAddressesDomain  :  sig 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  include  AbstractDomain . S 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  include  module  type  of  AbstractDomain . Map  ( AbstractAddress )  ( Attributes ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  val  empty  :  astate 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  val  add  :  AbstractAddress . t  ->  Invalidation . t  ->  astate  ->  astate 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  val  fold  : 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    ( AbstractAddress . t  ->  Invalidation . t  ->  ' accum  ->  ' accum )  ->  astate  ->  ' accum  ->  ' accum 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  val  invalidate  :  AbstractAddress . t  ->  Invalidation . t  ->  astate  ->  astate 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  val  get_invalidation  :  AbstractAddress . t  ->  astate  ->  Invalidation . t  option 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  (* *  None denotes a valid location  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					end  =  struct 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  include  AbstractDomain . Map  ( AbstractAddress )  ( Invalidation ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  module  Attribute  =  struct 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    (*  OPTIM: [Invalid _] is first in the order to make queries about invalidation status more 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					       efficient  ( only  need  to  look  at  the  first  element  in  the  set  of  attributes  to  know  if  an 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					       address  is  invalid )  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    type  t  =  Invalid  of  Invalidation . t  [ @@ deriving  compare ] 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    let  pp  f  =  function  Invalid  invalidation  ->  Invalidation . pp  f  invalidation 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  end 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  module  Attributes  =  AbstractDomain . FiniteSet  ( Attribute ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  include  AbstractDomain . Map  ( AbstractAddress )  ( Attributes ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  add_attribute  address  attribute  attribute_map  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    let  attributes  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      match  find_opt  address  attribute_map  with 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      |  Some  old_attributes  -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          Attributes . add  attribute  old_attributes 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      |  None  -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          Attributes . singleton  attribute 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    add  address  attributes  attribute_map 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  get_invalidation  address  invalids  =  find_opt  address  invalids 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  invalidate  address  invalidation  attribute_map  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    add_attribute  address  ( Attribute . Invalid  invalidation )  attribute_map 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  get_invalidation  address  attribute_map  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    (*  Since we often want to find out whether an address is invalid this case is optimised. Since 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					       [ Invalid  _ ]  attributes  are  the  smallest  we  can  simply  look  at  the  first  element  to  decide  if 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					       an  address  is  invalid  or  not .  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    find_opt  address  attribute_map 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    | >  Option . bind  ~ f : Attributes . min_elt_opt 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    | >  Option . map  ~ f : ( function  Attribute . Invalid  invalidation  ->  invalidation ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					end 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					(* *  the domain  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					type  t  =  { heap :  Memory . t ;  stack :  AliasingDomain . astate ;  invalids :  InvalidAddressesDomain . astate } 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					type  t  =  { heap :  Memory . t ;  stack :  AliasingDomain . astate ;  attributes:  Attribut  esDomain. astate } 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					let  initial  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  {  heap =  Memory . empty 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  ;  stack =  AliasingDomain . empty 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  ;  invalids = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      InvalidAddressesDomain . empty 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  ;  attribute s= 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      Attribut esDomain. empty 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      (*  TODO: this makes the analysis go a bit overboard with the Nullptr reports.  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      (*   (*  always recall that 0 is invalid  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         InvalidAddressesDomain . add  AbstractAddress . nullptr  Nullptr  InvalidAddressesDomain . empty  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         Attribut esDomain. add  AbstractAddress . nullptr  Nullptr  Attribut esDomain. empty  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  } 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -183,7 +212,7 @@ module Domain : AbstractDomain.S with type astate = t = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  type  astate  =  t 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  piecewise_lessthan  lhs  rhs  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    InvalidAddress esDomain. (  < =  )  ~ lhs : lhs . invalids ~ rhs : rhs . invalid  s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    Attribut esDomain. (  < =  )  ~ lhs : lhs . attributes ~ rhs : rhs . attribute  s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    &&  AliasingDomain . (  < =  )  ~ lhs : lhs . stack  ~ rhs : rhs . stack 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    &&  Memory . for_all 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         ( fun  addr_src  edges  -> 
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -285,8 +314,8 @@ module Domain : AbstractDomain.S with type astate = t = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					           stack1  stack2 ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    let  from_astate_union  { heap =  heap1 ;  stack =  stack1 ;  invalids=  invalid  s1} 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        { heap =  heap2 ;  stack =  stack2 ;  invalids=  invalid  s2}  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    let  from_astate_union  { heap =  heap1 ;  stack =  stack1 ;  attributes=  attribute  s1} 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        { heap =  heap2 ;  stack =  stack2 ;  attributes=  attribute  s2}  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      let  subst  =  AddressUF . create  ()  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      (*  gather equalities from the stacks  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      populate_subst_from_stacks  subst  stack1  stack2  ; 
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -297,12 +326,12 @@ module Domain : AbstractDomain.S with type astate = t = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         common  thanks  to  [ AbstractAddressDomain_JoinIsMin ]  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      let  stack  =  AliasingDomain . join  stack1  stack2  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      (*  basically union  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      let  invalids =  InvalidAddressesDomain . join  invalids1  invalid  s2 in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      { subst ;  astate =  { heap ;  stack ;  invalid s} } 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      let  attributes =  AttributesDomain . join  attributes1  attribute  s2 in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      { subst ;  astate =  { heap ;  stack ;  attribute s} } 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    (* *  compute new  set of invalid  addresses for a given join state *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    let  to_ invalids { subst ;  astate =  { invalids =  old_invalid  s}  as  astate }  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    (* *  compute new  address attribut es for a given join state *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    let  to_ attributes { subst ;  astate =  { attributes =  old_attribute  s}  as  astate }  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      (*  Is the address reachable from the stack variables? Since the new heap only has addresses 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         reachable  from  stack  variables  it  suffices  to  check  if  the  address  appears  in  either  the 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         heap  or  the  stack .  * ) 
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -310,35 +339,30 @@ module Domain : AbstractDomain.S with type astate = t = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Memory . mem  address  astate . heap 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        | |  AliasingDomain . exists  ( fun  _  value  ->  AbstractAddress . equal  value  address )  astate . stack 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      (*  given a previously known invalid address [old_address], add the new address that 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					         represents  it  to  [ new_invalids ]  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      let  add_old_invalid  astate  old_address  old_invalid  new_invalids  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      let  add_old_attribute  astate  old_address  old_attribute  new_attributes  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        (*  the address has to make sense for the new heap  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        let  repr  =  AddressUF . find  subst  old_address  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        let  new_address  =  ( repr  :>  AbstractAddress . t )  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        match  InvalidAddressesDomain . get_invalidation  new_address  new_invalids  with 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        |  Some  new_invalid  -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            (*  We have seen a representative of this address already: join. This can happen when 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					               several  previously  invalid  addresses  correspond  to  the  same  representative  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					               [ subst ] .  Doing  the  join  of  all  known  invalidation  reasons  to  make  results  more 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					               deterministic ( ? ) .   * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            InvalidAddressesDomain . add  new_address 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              ( Invalidation . join  new_invalid  old_invalid ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              new_invalids 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        match  AttributesDomain . find_opt  new_address  new_attributes  with 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        |  Some  new_attribute  -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            (*  We have seen a representative of this address already: join.   *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            AttributesDomain . add  new_address 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              ( AttributesDomain . Attributes . join  new_attribute  old_attribute ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              new_attributes 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        |  None  -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            (*  only record the  old invalidation  fact if the address is still reachable ( helps 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            (*  only record the attributes fact if the address is still reachable  ( helps 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					               convergence )  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  address_is_live  astate  new_address  then 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              InvalidAddressesDomain. add  new_address  old_invalid  new_invalid  s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              AttributesDomain. add  new_address  old_attribute  new_attribute  s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            else 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              (*  we can forget about the  fact that this location is invalid since nothing can 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                   refer  to  it   anymore  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              new_ invalid s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              (*  we can forget about the  attributes for this address since nothing can refer to it 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                 anymore  * ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              new_ attribute s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      InvalidAddress esDomain. fold 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ( fun  old_address  old_ invalid new_invalid  s -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          add_old_ invalid astate  old_address  old_invalid  new_invalid  s ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        old_ invalids InvalidAddress  esDomain. empty 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      Attribut esDomain. fold 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ( fun  old_address  old_ attribute new_attribute  s -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					          add_old_ attribute astate  old_address  old_attribute  new_attribute  s ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        old_ attributes Attribut  esDomain. empty 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    let  rec  normalize  state  = 
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -365,8 +389,8 @@ module Domain : AbstractDomain.S with type astate = t = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					              AddressUnionSet . pp  set  )  ; 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        L . d_decrease_indent  ()  ; 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        let  stack  =  AliasingDomain . map  ( to_canonical_address  state . subst )  state . astate . stack  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        let  invalids =  to_invalid  s state  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        { heap ;  stack ;  invalid s}  ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        let  attributes =  to_attribute  s state  in 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        { heap ;  stack ;  attribute s}  ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      else  normalize  { state  with  astate =  { state . astate  with  heap } } 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  end 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -424,9 +448,9 @@ module Domain : AbstractDomain.S with type astate = t = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    else  join  prev  next 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  pp  fmt  { heap ;  stack ;  invalid s}  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    F . fprintf  fmt  " {@[<v1> heap=@[<hv>%a@];@;stack=@[<hv>%a@];@; invalids=@[<hv>%a@];@]}"  Memory . pp  
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      heap  AliasingDomain . pp  stack  InvalidAddressesDomain. pp  invalid  s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  pp  fmt  { heap ;  stack ;  attribute s}  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    F . fprintf  fmt  " {@[<v1> heap=@[<hv>%a@];@;stack=@[<hv>%a@];@; attributes=@[<hv>%a@];@]}"  
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					      Memory . pp  heap  AliasingDomain . pp  stack  AttributesDomain. pp  attribute  s
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					end 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					(*  {2 Access operations on the domain}  *) 
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -469,15 +493,15 @@ module Diagnostic = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    Invalidation . issue_type_of_cause  invalidated_by 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					end 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					type  ' a  access_result  =  ( ' a ,  Diagnostic . t )  result 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					(* *  operations on the domain  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					module  Operations  =  struct 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  open  Result . Monad_infix 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  type  ' a  access_result  =  ( ' a ,  Diagnostic . t )  result 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  (* *  Check that the address is not known to be invalid  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  check_addr_access  actor  address  astate  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    match  InvalidAddressesDomain. get_invalidation  address  astate . invalid  s with 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    match  AttributesDomain. get_invalidation  address  astate . attribute  s with 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    |  Some  invalidated_by  -> 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Error  ( Diagnostic . AccessToInvalidAddress  { invalidated_by ;  accessed_by =  actor ;  address } ) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    |  None  -> 
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -559,7 +583,7 @@ module Operations = struct
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  (* *  Add the given address to the set of know invalid addresses.  *) 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  mark_invalid  actor  address  astate  = 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    { astate  with  invalids=  InvalidAddressesDomain . add  address  actor  astate . invalid  s} 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    { astate  with  attributes=  AttributesDomain . invalidate  address  actor  astate . attribute  s} 
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  let  havoc_var  var  astate  =