@ -74,8 +74,10 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					    (*  get the node associated with [exp] in [access_tree]  *) 
 
			
		
	
		
			
				
					    let  rec  hil_exp_get_node  ? ( abstracted =  false )  ( exp :  HilExp . t )  access_tree  proc_data  = 
 
			
		
	
		
			
				
					      match  exp  with 
 
			
		
	
		
			
				
					      |  AccessPath  access_path  -> 
 
			
		
	
		
			
				
					          exp_get_node_  ~ abstracted  access_path  access_tree  proc_data 
 
			
		
	
		
			
				
					      |  AccessExpression  access_expr  -> 
 
			
		
	
		
			
				
					          exp_get_node_  ~ abstracted 
 
			
		
	
		
			
				
					            ( AccessExpression . to_access_path  access_expr ) 
 
			
		
	
		
			
				
					            access_tree  proc_data 
 
			
		
	
		
			
				
					      |  Cast  ( _ ,  e )  |  Exception  e  |  UnaryOperator  ( _ ,  e ,  _ )  -> 
 
			
		
	
		
			
				
					          hil_exp_get_node  ~ abstracted  e  access_tree  proc_data 
 
			
		
	
		
			
				
					      |  BinaryOperator  ( _ ,  e1 ,  e2 )  ->  ( 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -99,8 +101,10 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    let  add_actual_source  source  index  actuals  access_tree  proc_data  = 
 
			
		
	
		
			
				
					      match  List . nth_exn  actuals  index  with 
 
			
		
	
		
			
				
					      |  HilExp . AccessPath  actual_ap_raw  -> 
 
			
		
	
		
			
				
					          let  actual_ap  =  AccessPath . Abs . Abstracted  actual_ap_raw  in 
 
			
		
	
		
			
				
					      |  HilExp . AccessExpression  actual_ae_raw  -> 
 
			
		
	
		
			
				
					          let  actual_ap  = 
 
			
		
	
		
			
				
					            AccessPath . Abs . Abstracted  ( AccessExpression . to_access_path  actual_ae_raw ) 
 
			
		
	
		
			
				
					          in 
 
			
		
	
		
			
				
					          let  trace  =  access_path_get_trace  actual_ap  access_tree  proc_data  in 
 
			
		
	
		
			
				
					          TaintDomain . add_trace  actual_ap  ( TraceDomain . add_source  source  trace )  access_tree 
 
			
		
	
		
			
				
					      |  _  -> 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -332,11 +336,13 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					              let  actual_trace'  =  TraceDomain . add_sink  sink'  actual_trace  in 
 
			
		
	
		
			
				
					              report_trace  actual_trace'  callee_site  proc_data  ; 
 
			
		
	
		
			
				
					              match  exp  with 
 
			
		
	
		
			
				
					              |  HilExp . Access Path actual_ap  _raw
 
			
		
	
		
			
				
					              |  HilExp . Access Expression actual_ae  _raw
 
			
		
	
		
			
				
					                when  not 
 
			
		
	
		
			
				
					                       ( TraceDomain . Sources . Footprint . is_empty 
 
			
		
	
		
			
				
					                          ( TraceDomain . sources  actual_trace' ) . footprint )  -> 
 
			
		
	
		
			
				
					                  let  actual_ap  =  AccessPath . Abs . Abstracted  actual_ap_raw  in 
 
			
		
	
		
			
				
					                  let  actual_ap  = 
 
			
		
	
		
			
				
					                    AccessPath . Abs . Abstracted  ( AccessExpression . to_access_path  actual_ae_raw ) 
 
			
		
	
		
			
				
					                  in 
 
			
		
	
		
			
				
					                  TaintDomain . add_trace  actual_ap  actual_trace'  access_tree_acc 
 
			
		
	
		
			
				
					              |  _  -> 
 
			
		
	
		
			
				
					                  (*  no more sources can flow into this sink; no sense in keeping track of it  *) 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -386,8 +392,10 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					            ( projected_ap_opt ,  Option . value  ~ default : TaintDomain . empty_node  caller_node_opt ) 
 
			
		
	
		
			
				
					        |  Var . LogicalVar  id  when  Ident . is_footprint  id  ->  ( 
 
			
		
	
		
			
				
					          match  List . nth  actuals  ( Ident . get_stamp  id )  with 
 
			
		
	
		
			
				
					          |  Some  HilExp . AccessPath  actual_ap  -> 
 
			
		
	
		
			
				
					              let  projected_ap  =  project  ~ formal_ap  ~ actual_ap  in 
 
			
		
	
		
			
				
					          |  Some  HilExp . AccessExpression  actual_ae  -> 
 
			
		
	
		
			
				
					              let  projected_ap  = 
 
			
		
	
		
			
				
					                project  ~ formal_ap  ~ actual_ap : ( AccessExpression . to_access_path  actual_ae ) 
 
			
		
	
		
			
				
					              in 
 
			
		
	
		
			
				
					              let  caller_node_opt  =  access_path_get_node  projected_ap  access_tree  proc_data  in 
 
			
		
	
		
			
				
					              ( Some  projected_ap ,  Option . value  ~ default : TaintDomain . empty_node  caller_node_opt ) 
 
			
		
	
		
			
				
					          |  Some  exp  -> 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -448,7 +456,10 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					          |  AccessPath . ArrayAccess  ( _ ,  indexes )  -> 
 
			
		
	
		
			
				
					              let  dummy_call_site  =  CallSite . make  BuiltinDecl . __array_access  loc  in 
 
			
		
	
		
			
				
					              let  dummy_actuals  = 
 
			
		
	
		
			
				
					                List . map  ~ f : ( fun  index_ap  ->  HilExp . AccessPath  index_ap )  indexes 
 
			
		
	
		
			
				
					                List . map 
 
			
		
	
		
			
				
					                  ~ f : ( fun  index_ap  -> 
 
			
		
	
		
			
				
					                    HilExp . AccessExpression  ( AccessExpression . of_access_path  index_ap )  ) 
 
			
		
	
		
			
				
					                  indexes 
 
			
		
	
		
			
				
					              in 
 
			
		
	
		
			
				
					              let  sinks  = 
 
			
		
	
		
			
				
					                TraceDomain . Sink . get  dummy_call_site  dummy_actuals  proc_data . ProcData . tenv 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -464,7 +475,11 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					      let  add_sources_for_access_path  ( ( ( var ,  _ ) ,  _ )  as  ap )  loc  astate  = 
 
			
		
	
		
			
				
					        if  Var . is_global  var  then 
 
			
		
	
		
			
				
					          let  dummy_call_site  =  CallSite . make  BuiltinDecl . __global_access  loc  in 
 
			
		
	
		
			
				
					          match  TraceDomain . Source . get  dummy_call_site  [ HilExp . AccessPath  ap ]  proc_data . tenv  with 
 
			
		
	
		
			
				
					          match 
 
			
		
	
		
			
				
					            TraceDomain . Source . get  dummy_call_site 
 
			
		
	
		
			
				
					              [ HilExp . AccessExpression  ( AccessExpression . of_access_path  ap ) ] 
 
			
		
	
		
			
				
					              proc_data . tenv 
 
			
		
	
		
			
				
					          with 
 
			
		
	
		
			
				
					          |  Some  { TraceDomain . Source . source }  -> 
 
			
		
	
		
			
				
					              let  access_path  =  AccessPath . Abs . Exact  ap  in 
 
			
		
	
		
			
				
					              let  trace ,  subtree  = 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -479,7 +494,8 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					      in 
 
			
		
	
		
			
				
					      let  add_sources_sinks_for_exp  exp  loc  astate  = 
 
			
		
	
		
			
				
					        match  exp  with 
 
			
		
	
		
			
				
					        |  HilExp . AccessPath  access_path  -> 
 
			
		
	
		
			
				
					        |  HilExp . AccessExpression  access_expr  -> 
 
			
		
	
		
			
				
					            let  access_path  =  AccessExpression . to_access_path  access_expr  in 
 
			
		
	
		
			
				
					            add_sinks_for_access_path  access_path  loc  astate 
 
			
		
	
		
			
				
					            | >  add_sources_for_access_path  access_path  loc 
 
			
		
	
		
			
				
					        |  _  -> 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -572,15 +588,17 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					                  propagate_to_access_path  ( AccessPath . Abs . Abstracted  ( ret_ap ,  [] ) )  actuals 
 
			
		
	
		
			
				
					                    astate_acc 
 
			
		
	
		
			
				
					              |  (  TaintSpec . Propagate_to_receiver 
 
			
		
	
		
			
				
					                ,  ( Access Path receiver_ap  )  ::  ( _  ::  _  as  other_actuals ) 
 
			
		
	
		
			
				
					                ,  ( Access Expression receiver_ae  )  ::  ( _  ::  _  as  other_actuals ) 
 
			
		
	
		
			
				
					                ,  _  )  -> 
 
			
		
	
		
			
				
					                  propagate_to_access_path  ( AccessPath . Abs . Abstracted  receiver_ap )  other_actuals 
 
			
		
	
		
			
				
					                    astate_acc 
 
			
		
	
		
			
				
					                  propagate_to_access_path 
 
			
		
	
		
			
				
					                    ( AccessPath . Abs . Abstracted  ( AccessExpression . to_access_path  receiver_ae ) ) 
 
			
		
	
		
			
				
					                    other_actuals  astate_acc 
 
			
		
	
		
			
				
					              |  TaintSpec . Propagate_to_actual  actual_index ,  _ ,  _  ->  ( 
 
			
		
	
		
			
				
					                match  List . nth  actuals  actual_index  with 
 
			
		
	
		
			
				
					                |  Some  HilExp . AccessPath  actual_ap  -> 
 
			
		
	
		
			
				
					                    propagate_to_access_path  ( AccessPath . Abs . Abstracted  actual_ap )  actuals 
 
			
		
	
		
			
				
					                      astate_acc 
 
			
		
	
		
			
				
					                |  Some  HilExp . AccessExpression  actual_ae  -> 
 
			
		
	
		
			
				
					                    propagate_to_access_path 
 
			
		
	
		
			
				
					                      ( AccessPath . Abs . Abstracted  ( AccessExpression . to_access_path  actual_ae ) ) 
 
			
		
	
		
			
				
					                      actuals  astate_acc 
 
			
		
	
		
			
				
					                |  _  -> 
 
			
		
	
		
			
				
					                    astate_acc  ) 
 
			
		
	
		
			
				
					              |  _  -> 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -593,20 +611,27 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					            |  " operator= "  when  not  ( Typ . Procname . is_java  callee_pname )  ->  ( 
 
			
		
	
		
			
				
					              match  (*  treat unknown calls to C++ operator= as assignment  *) 
 
			
		
	
		
			
				
					                    actuals  with 
 
			
		
	
		
			
				
					              |  [ ( AccessPath  lhs_access_path ) ;  rhs_exp ]  -> 
 
			
		
	
		
			
				
					                  exec_write  lhs_access_path  rhs_exp  access_tree 
 
			
		
	
		
			
				
					              |  [  ( AccessPath  lhs_access_path ) 
 
			
		
	
		
			
				
					                ;  rhs_exp 
 
			
		
	
		
			
				
					                ;  ( HilExp . AccessPath  ( ( ( Var . ProgramVar  pvar ,  _ ) ,  [] )  as  dummy_ret_access_path ) )  ] 
 
			
		
	
		
			
				
					                when  Pvar . is_frontend_tmp  pvar  -> 
 
			
		
	
		
			
				
					              |  [ ( AccessExpression  lhs_access_expr ) ;  rhs_exp ]  -> 
 
			
		
	
		
			
				
					                  exec_write  ( AccessExpression . to_access_path  lhs_access_expr )  rhs_exp  access_tree 
 
			
		
	
		
			
				
					              |  [ ( AccessExpression  lhs_access_expr ) ;  rhs_exp ;  ( HilExp . AccessExpression  access_expr ) ] 
 
			
		
	
		
			
				
					                ->  ( 
 
			
		
	
		
			
				
					                  let  dummy_ret_access_path  =  AccessExpression . to_access_path  access_expr  in 
 
			
		
	
		
			
				
					                  match  dummy_ret_access_path  with 
 
			
		
	
		
			
				
					                  |  ( Var . ProgramVar  pvar ,  _ ) ,  []  when  Pvar . is_frontend_tmp  pvar  -> 
 
			
		
	
		
			
				
					                      (*  the frontend translates operator= ( x, y )  as operator= ( x, y, dummy_ret )  when 
 
			
		
	
		
			
				
					                     operator =  returns  a  value  type  * ) 
 
			
		
	
		
			
				
					                  exec_write  lhs_access_path  rhs_exp  access_tree 
 
			
		
	
		
			
				
					                      exec_write 
 
			
		
	
		
			
				
					                        ( AccessExpression . to_access_path  lhs_access_expr ) 
 
			
		
	
		
			
				
					                        rhs_exp  access_tree 
 
			
		
	
		
			
				
					                      | >  exec_write  dummy_ret_access_path  rhs_exp 
 
			
		
	
		
			
				
					                  |  _  -> 
 
			
		
	
		
			
				
					                      L . internal_error  " Unexpected call to operator= %a in %a "  HilInstr . pp  instr 
 
			
		
	
		
			
				
					                        Typ . Procname . pp  callee_pname  ; 
 
			
		
	
		
			
				
					                      access_tree  ) 
 
			
		
	
		
			
				
					              |  _  -> 
 
			
		
	
		
			
				
					                  L . internal_error  " Unexpected call to operator= %a in %a "  HilInstr . pp  instr 
 
			
		
	
		
			
				
					                    Typ . Procname . pp  callee_pname  ; 
 
			
		
	
		
			
				
					                  access_tree  ) 
 
			
		
	
		
			
				
					            |  _  -> 
 
			
		
	
		
			
				
					                let  model  = 
 
			
		
	
		
			
				
					                  TaintSpecification . handle_unknown_call  callee_pname  ( Option . map  ~ f : snd  ret_opt ) 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -623,11 +648,14 @@ module Make (TaintSpecification : TaintSpec.S) = struct
 
			
		
	
		
			
				
					                   assigning  to  it .  understand  this  pattern  by  pretending  it's  the  return  value  * ) 
 
			
		
	
		
			
				
					                List . last  actuals 
 
			
		
	
		
			
				
					              with 
 
			
		
	
		
			
				
					              |  Some  HilExp . AccessPath  ( ( ( Var . ProgramVar  pvar ,  _ )  as  ret_base ) ,  [] ) 
 
			
		
	
		
			
				
					                when  Pvar . is_frontend_tmp  pvar  -> 
 
			
		
	
		
			
				
					              |  Some  HilExp . AccessExpression  access_expr  ->  ( 
 
			
		
	
		
			
				
					                match  AccessExpression . to_access_path  access_expr  with 
 
			
		
	
		
			
				
					                |  ( ( Var . ProgramVar  pvar ,  _ )  as  ret_base ) ,  []  when  Pvar . is_frontend_tmp  pvar  -> 
 
			
		
	
		
			
				
					                    Some  ret_base 
 
			
		
	
		
			
				
					                |  _  -> 
 
			
		
	
		
			
				
					                    None  ) 
 
			
		
	
		
			
				
					              |  _  -> 
 
			
		
	
		
			
				
					                  None  ) 
 
			
		
	
		
			
				
					            |  _  -> 
 
			
		
	
		
			
				
					                ret_opt 
 
			
		
	
		
			
				
					          in