@@ -1097,20 +1097,15 @@ struct
1097
1097
| Int x -> ValueDomain.ID. to_int x
1098
1098
| _ -> None
1099
1099
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
1114
1109
1115
1110
(* * Evaluate expression as address.
1116
1111
Avoids expensive Apron EvalInt if the Int result would be useless to us anyway. *)
@@ -1204,10 +1199,7 @@ struct
1204
1199
let query ctx (type a ) (q : a Q.t ): a Q.result =
1205
1200
match q with
1206
1201
| 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
1211
1203
| Q. EvalJumpBuf e ->
1212
1204
begin match eval_rv_address (Analyses. ask_of_ctx ctx) ctx.global ctx.local e with
1213
1205
| Address jmp_buf ->
@@ -2411,34 +2403,38 @@ struct
2411
2403
in
2412
2404
if get_bool " sem.noreturn.dead_code" && Cil. hasAttribute " noreturn" f.vattr then raise Deadcode else st
2413
2405
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 =
2415
2407
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
2442
2438
2443
2439
let combine_env ctx lval fexp f args fc au (f_ask : Queries.ask ) =
2444
2440
let combine_one (st : D.t ) (fun_st : D.t ) =
@@ -2453,9 +2449,9 @@ struct
2453
2449
let cpa_noreturn = CPA. remove (return_varinfo () ) fun_st.cpa in
2454
2450
let ask = (Analyses. ask_of_ctx ctx) in
2455
2451
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;
2457
2453
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
2459
2455
let cpa_local = CPA. filter (fun x _ -> not (is_global ask x)) st.cpa in
2460
2456
let cpa' = CPA. fold CPA. add cpa_noreturn cpa_local in (* add cpa_noreturn to cpa_local *)
2461
2457
if M. tracing then M. trace " taintPC" " combined: %a\n " CPA. pretty cpa';
@@ -2470,7 +2466,10 @@ struct
2470
2466
let cpa_caller' = CPA. fold CPA. add cpa_new cpa_caller in
2471
2467
if M. tracing then M. trace " taintPC" " cpa_caller': %a\n " CPA. pretty cpa_caller';
2472
2468
(* 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
2474
2473
let st_combined = combine_st ctx {st with cpa = cpa_caller'} fun_st tainted in
2475
2474
if M. tracing then M. trace " taintPC" " combined: %a\n " CPA. pretty st_combined.cpa;
2476
2475
{ fun_st with cpa = st_combined.cpa }
0 commit comments