@ -83,7 +83,10 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
 
			
		
	
		
			
				
					      path_state 
 
			
		
	
		
			
				
					      ( AccessPath . of_exp  exp  typ  ~ f_resolve_id : ( fun  _  ->  None ) ) 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					  let  exec_instr  ( ( lockstate ,  ( readstate , writestate ) )  as  astate )  {  ProcData . pdesc ;  tenv ;  }  _  = 
 
			
		
	
		
			
				
					  let  exec_instr 
 
			
		
	
		
			
				
					      ( {  ThreadSafetyDomain . locks ;  reads ;  writes ;  }  as  astate ) 
 
			
		
	
		
			
				
					      {  ProcData . pdesc ;  tenv ;  }  _  = 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    let  is_unprotected  is_locked  = 
 
			
		
	
		
			
				
					      not  is_locked  &&  not  ( Procdesc . is_java_synchronized  pdesc )  in 
 
			
		
	
		
			
				
					    function 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -92,41 +95,44 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
 
			
		
	
		
			
				
					          (*  assuming that modeled procedures do not have useful summaries  *) 
 
			
		
	
		
			
				
					          match  get_lock_model  pn  with 
 
			
		
	
		
			
				
					          |  Lock  -> 
 
			
		
	
		
			
				
					              true ,  snd  astate 
 
			
		
	
		
			
				
					              {  astate  with  locks  =  true ;  } 
 
			
		
	
		
			
				
					          |  Unlock  -> 
 
			
		
	
		
			
				
					              false ,  snd  astate 
 
			
		
	
		
			
				
					              {  astate  with  locks  =  false ;  } 
 
			
		
	
		
			
				
					          |  None  -> 
 
			
		
	
		
			
				
					              begin 
 
			
		
	
		
			
				
					                match  Summary . read_summary  pdesc  pn  with 
 
			
		
	
		
			
				
					                |  Some  ( callee_lockstate ,  ( callee_reads ,  callee_writes ) ) -> 
 
			
		
	
		
			
				
					                    let  locks tate ' =  callee_ lockstate  | |  locks tate  in 
 
			
		
	
		
			
				
					                    let  _ ,  re ad_write state' = 
 
			
		
	
		
			
				
					                |  Some  callee_astate -> 
 
			
		
	
		
			
				
					                    let  locks ' =  callee_ astate.  locks | |  locks  in 
 
			
		
	
		
			
				
					                    let  = 
 
			
		
	
		
			
				
					                      (*  TODO  ( 14842325 ) : report on constructors that aren't threadsafe 
 
			
		
	
		
			
				
					                         ( e . g . ,  constructors  that  access  static  fields )  * ) 
 
			
		
	
		
			
				
					                      if  is_unprotected  locks tate ' && 
 
			
		
	
		
			
				
					                      if  is_unprotected  locks ' && 
 
			
		
	
		
			
				
					                         not  ( is_initializer  tenv  pn )  && 
 
			
		
	
		
			
				
					                         not  ( is_call_to_builder_class_method  pn ) 
 
			
		
	
		
			
				
					                      then 
 
			
		
	
		
			
				
					                        let  call_site  =  CallSite . make  pn  loc  in 
 
			
		
	
		
			
				
					                        let  callee_reads tate  = 
 
			
		
	
		
			
				
					                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ reads call_site  in 
 
			
		
	
		
			
				
					                        let  callee_writes tate  = 
 
			
		
	
		
			
				
					                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ writes call_site  in 
 
			
		
	
		
			
				
					                        let  callee_astate  = 
 
			
		
	
		
			
				
					                          callee_lockstate ,  ( callee_readstate ,  callee_writestate ) in 
 
			
		
	
		
			
				
					                        ThreadSafetyDomain . join  callee_astate  astate 
 
			
		
	
		
			
				
					                        let  callee_reads  = 
 
			
		
	
		
			
				
					                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ astate.  reads call_site  in 
 
			
		
	
		
			
				
					                        let  callee_writes  = 
 
			
		
	
		
			
				
					                          ThreadSafetyDomain . PathDomain . with_callsite  callee_ astate.  writes call_site  in 
 
			
		
	
		
			
				
					                        let  callee_astate '  = 
 
			
		
	
		
			
				
					                          {  callee_astate  with  ThreadSafetyDomain . reads  =  callee_reads ;  writes  =  callee_writes ;  } in 
 
			
		
	
		
			
				
					                        ThreadSafetyDomain . join  callee_astate '  astate 
 
			
		
	
		
			
				
					                      else 
 
			
		
	
		
			
				
					                        astate  in 
 
			
		
	
		
			
				
					                    lockstate' ,  read_writestate' 
 
			
		
	
		
			
				
					                    {  astate'  with  locks  =  locks'  } 
 
			
		
	
		
			
				
					                |  None  -> 
 
			
		
	
		
			
				
					                    astate 
 
			
		
	
		
			
				
					              end 
 
			
		
	
		
			
				
					        end 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    |  Sil . Store  ( ( Lfield  (  _ ,  _ ,  typ )  as  lhsfield )  ,  _ ,  _ ,  loc )  -> 
 
			
		
	
		
			
				
					        if  is_unprotected  lockstate  then  (*  abstracts no lock being held *) 
 
			
		
	
		
			
				
					          ( lockstate ,  ( readstate ,  add_path_to_state  lhsfield  typ  loc  writestate ) ) 
 
			
		
	
		
			
				
					        else  astate 
 
			
		
	
		
			
				
					        if  is_unprotected  locks  (*  abstracts no lock being held  *) 
 
			
		
	
		
			
				
					        then 
 
			
		
	
		
			
				
					          let  writes'  =  add_path_to_state  lhsfield  typ  loc  writes  in 
 
			
		
	
		
			
				
					          {  astate  with  writes  =  writes' ;  } 
 
			
		
	
		
			
				
					        else 
 
			
		
	
		
			
				
					          astate 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    (*  Note: it appears that the third arg of Store is never an Lfield in the targets of, 
 
			
		
	
		
			
				
					       our  translations ,  which  is  why  we  have  not  covered  that  case .  * ) 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -134,9 +140,12 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
 
			
		
	
		
			
				
					        failwith  " Unexpected store instruction with rhs field " 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    |  Sil . Load  ( _ ,  ( Lfield  (  _ ,  _ ,  typ )  as  rhsfield )  ,  _ ,  loc )  -> 
 
			
		
	
		
			
				
					        if  is_unprotected  lockstate  then  (*  abstracts no lock being held *) 
 
			
		
	
		
			
				
					          ( lockstate ,  ( add_path_to_state  rhsfield  typ  loc  readstate ,  writestate ) ) 
 
			
		
	
		
			
				
					        else  astate 
 
			
		
	
		
			
				
					        if  is_unprotected  locks  (*  abstracts no lock being held  *) 
 
			
		
	
		
			
				
					        then 
 
			
		
	
		
			
				
					          let  reads'  =  add_path_to_state  rhsfield  typ  loc  reads  in 
 
			
		
	
		
			
				
					          {  astate  with  reads  =  reads' ;  } 
 
			
		
	
		
			
				
					        else 
 
			
		
	
		
			
				
					          astate 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    |   _   -> 
 
			
		
	
		
			
				
					        astate 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -224,7 +233,7 @@ let report_thread_safety_errors ( _, tenv, pname, pdesc) trace =
 
			
		
	
		
			
				
					  let  open  ThreadSafetyDomain  in 
 
			
		
	
		
			
				
					  let  trace_of_pname  callee_pname  = 
 
			
		
	
		
			
				
					    match  Summary . read_summary  pdesc  callee_pname  with 
 
			
		
	
		
			
				
					    |  Some  ( _ ,  ( _ ,  callee_trace ) )  ->  callee_trace 
 
			
		
	
		
			
				
					    |  Some  astate  ->  astate . writes 
 
			
		
	
		
			
				
					    |  _  ->  PathDomain . initial  in 
 
			
		
	
		
			
				
					  let  report_one_path  ( ( _ ,  sinks )  as  path )  = 
 
			
		
	
		
			
				
					    let  pp_accesses  fmt  sink  = 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -261,9 +270,9 @@ let report_thread_safety_errors ( _, tenv, pname, pdesc) trace =
 
			
		
	
		
			
				
					   This  indicates  that  the  method  races  with  itself .  To  be  refined  later .  * ) 
 
			
		
	
		
			
				
					let  process_results_table  tab  =  
			
		
	
		
			
				
					  ResultsTableType . iter    (*  report errors for each method  *) 
 
			
		
	
		
			
				
					    ( fun  proc_env  (  _ , (  _ ,  writestate )  )  -> 
 
			
		
	
		
			
				
					    ( fun  proc_env  ( astate  :  ThreadSafetyDomain . astate )  -> 
 
			
		
	
		
			
				
					       if  should_report_on_proc  proc_env  then 
 
			
		
	
		
			
				
					         report_thread_safety_errors  proc_env  tate 
 
			
		
	
		
			
				
					         report_thread_safety_errors  proc_env  astate.  writes
 
			
		
	
		
			
				
					       else  () 
 
			
		
	
		
			
				
					    ) 
 
			
		
	
		
			
				
					    tab