@@ -1097,20 +1097,15 @@ struct
10971097 | Int x -> ValueDomain.ID. to_int x
10981098 | _ -> None
10991099
1100- let eval_funvar ctx fval : varinfo list =
1101- let exception OnlyUnknown in
1102- try
1103- let fp = eval_fv (Analyses. ask_of_ctx ctx) ctx.global ctx.local fval in
1104- if AD. mem Addr. UnknownPtr fp then begin
1105- let others = AD. to_var_may fp in
1106- if others = [] then raise OnlyUnknown ;
1107- M. warn ~category: Imprecise ~tags: [Category Call ] " Function pointer %a may contain unknown functions." d_exp fval;
1108- dummyFunDec.svar :: others
1109- end else
1110- AD. to_var_may fp
1111- with SetDomain. Unsupported _ | OnlyUnknown ->
1112- M. warn ~category: Imprecise ~tags: [Category Call ] " Unknown call to function %a." d_exp fval;
1113- [dummyFunDec.svar]
1100+ let eval_funvar ctx fval : Queries.AD.t =
1101+ let fp = eval_fv (Analyses. ask_of_ctx ctx) ctx.global ctx.local fval in
1102+ if AD. is_top fp then (
1103+ if AD. cardinal fp = 1 then
1104+ M. warn ~category: Imprecise ~tags: [Category Call ] " Unknown call to function %a." d_exp fval
1105+ else
1106+ M. warn ~category: Imprecise ~tags: [Category Call ] " Function pointer %a may contain unknown functions." d_exp fval
1107+ );
1108+ fp
11141109
11151110 (* * Evaluate expression as address.
11161111 Avoids expensive Apron EvalInt if the Int result would be useless to us anyway. *)
@@ -1204,10 +1199,7 @@ struct
12041199 let query ctx (type a ) (q : a Q.t ): a Q.result =
12051200 match q with
12061201 | Q. EvalFunvar e ->
1207- begin
1208- let fs = eval_funvar ctx e in
1209- List. fold_left (fun xs v -> Q.LS. add (v,`NoOffset ) xs) (Q.LS. empty () ) fs
1210- end
1202+ eval_funvar ctx e
12111203 | Q. EvalJumpBuf e ->
12121204 begin match eval_rv_address (Analyses. ask_of_ctx ctx) ctx.global ctx.local e with
12131205 | Address jmp_buf ->
@@ -2411,34 +2403,38 @@ struct
24112403 in
24122404 if get_bool " sem.noreturn.dead_code" && Cil. hasAttribute " noreturn" f.vattr then raise Deadcode else st
24132405
2414- let combine_st ctx (local_st : store ) (fun_st : store ) (tainted_lvs : Q.LS .t ) : store =
2406+ let combine_st ctx (local_st : store ) (fun_st : store ) (tainted_lvs : AD .t ) : store =
24152407 let ask = (Analyses. ask_of_ctx ctx) in
2416- Q.LS. fold (fun (v , o ) st ->
2417- if CPA. mem v fun_st.cpa then
2418- let lval = Mval.Exp. to_cil (v,o) in
2419- let address = eval_lv ask ctx.global st lval in
2420- let lval_type = (AD. type_of address) in
2421- if M. tracing then M. trace " taintPC" " updating %a; type: %a\n " Mval.Exp. pretty (v, o) d_type lval_type;
2422- match (CPA. find_opt v (fun_st.cpa)), lval_type with
2423- | None , _ -> st
2424- (* partitioned arrays cannot be copied by individual lvalues, so if tainted just copy the whole callee value for the array variable *)
2425- | Some (Array a ), _ when (CArrays. domain_of_t a) = PartitionedDomain -> {st with cpa = CPA. add v (Array a) st.cpa}
2426- (* "get" returned "unknown" when applied to a void type, so special case void types. This caused problems with some sv-comps (e.g. regtest 64 11) *)
2427- | Some voidVal , TVoid _ -> {st with cpa = CPA. add v voidVal st.cpa}
2428- | _ , _ -> begin
2429- let new_val = get ask ctx.global fun_st address None in
2430- if M. tracing then M. trace " taintPC" " update val: %a\n\n " VD. pretty new_val;
2431- let st' = set_savetop ~ctx ask ctx.global st address lval_type new_val in
2432- let partDep = Dep. find_opt v fun_st.deps in
2433- match partDep with
2434- | None -> st'
2435- (* if a var partitions an array, all cpa-info for arrays it may partition are added from callee to caller *)
2436- | Some deps -> {st' with cpa = (Dep.VarSet. fold (fun v accCPA -> let val_opt = CPA. find_opt v fun_st.cpa in
2437- match val_opt with
2438- | None -> accCPA
2439- | Some new_val -> CPA. add v new_val accCPA ) deps st'.cpa)}
2440- end
2441- else st) tainted_lvs local_st
2408+ AD. fold (fun addr st ->
2409+ match addr with
2410+ | Addr. Addr (v ,o ) ->
2411+ if CPA. mem v fun_st.cpa then
2412+ let lval = Addr.Mval. to_cil (v,o) in
2413+ let address = eval_lv ask ctx.global st lval in
2414+ let lval_type = Addr. type_of addr in
2415+ if M. tracing then M. trace " taintPC" " updating %a; type: %a\n " Addr.Mval. pretty (v,o) d_type lval_type;
2416+ match (CPA. find_opt v (fun_st.cpa)), lval_type with
2417+ | None , _ -> st
2418+ (* partitioned arrays cannot be copied by individual lvalues, so if tainted just copy the whole callee value for the array variable *)
2419+ | Some (Array a ), _ when (CArrays. domain_of_t a) = PartitionedDomain -> {st with cpa = CPA. add v (Array a) st.cpa}
2420+ (* "get" returned "unknown" when applied to a void type, so special case void types. This caused problems with some sv-comps (e.g. regtest 64 11) *)
2421+ | Some voidVal , TVoid _ -> {st with cpa = CPA. add v voidVal st.cpa}
2422+ | _ , _ -> begin
2423+ let new_val = get ask ctx.global fun_st address None in
2424+ if M. tracing then M. trace " taintPC" " update val: %a\n\n " VD. pretty new_val;
2425+ let st' = set_savetop ~ctx ask ctx.global st address lval_type new_val in
2426+ let partDep = Dep. find_opt v fun_st.deps in
2427+ match partDep with
2428+ | None -> st'
2429+ (* if a var partitions an array, all cpa-info for arrays it may partition are added from callee to caller *)
2430+ | Some deps -> {st' with cpa = (Dep.VarSet. fold (fun v accCPA -> let val_opt = CPA. find_opt v fun_st.cpa in
2431+ match val_opt with
2432+ | None -> accCPA
2433+ | Some new_val -> CPA. add v new_val accCPA ) deps st'.cpa)}
2434+ end
2435+ else st
2436+ | _ -> st
2437+ ) tainted_lvs local_st
24422438
24432439 let combine_env ctx lval fexp f args fc au (f_ask : Queries.ask ) =
24442440 let combine_one (st : D.t ) (fun_st : D.t ) =
@@ -2453,9 +2449,9 @@ struct
24532449 let cpa_noreturn = CPA. remove (return_varinfo () ) fun_st.cpa in
24542450 let ask = (Analyses. ask_of_ctx ctx) in
24552451 let tainted = f_ask.f Q. MayBeTainted in
2456- if M. tracing then M. trace " taintPC" " combine for %s in base: tainted: %a\n " f.svar.vname Q.LS . pretty tainted;
2452+ if M. tracing then M. trace " taintPC" " combine for %s in base: tainted: %a\n " f.svar.vname AD . pretty tainted;
24572453 if M. tracing then M. trace " taintPC" " combine base:\n caller: %a\n callee: %a\n " CPA. pretty st.cpa CPA. pretty fun_st.cpa;
2458- if Q.LS . is_top tainted then
2454+ if AD . is_top tainted then
24592455 let cpa_local = CPA. filter (fun x _ -> not (is_global ask x)) st.cpa in
24602456 let cpa' = CPA. fold CPA. add cpa_noreturn cpa_local in (* add cpa_noreturn to cpa_local *)
24612457 if M. tracing then M. trace " taintPC" " combined: %a\n " CPA. pretty cpa';
@@ -2470,7 +2466,10 @@ struct
24702466 let cpa_caller' = CPA. fold CPA. add cpa_new cpa_caller in
24712467 if M. tracing then M. trace " taintPC" " cpa_caller': %a\n " CPA. pretty cpa_caller';
24722468 (* remove lvals from the tainted set that correspond to variables for which we just added a new mapping from the callee*)
2473- let tainted = Q.LS. filter (fun (v , _ ) -> not (CPA. mem v cpa_new)) tainted in
2469+ let tainted = AD. filter (function
2470+ | Addr. Addr (v ,_ ) -> not (CPA. mem v cpa_new)
2471+ | _ -> false
2472+ ) tainted in
24742473 let st_combined = combine_st ctx {st with cpa = cpa_caller'} fun_st tainted in
24752474 if M. tracing then M. trace " taintPC" " combined: %a\n " CPA. pretty st_combined.cpa;
24762475 { fun_st with cpa = st_combined.cpa }
0 commit comments