[racerd] less boiler-plate in reporting violations

Summary: The pattern "check if an access has already been reported, otherwise see if it is a violation, report it, then add it to the set of reported accesses" is too much copy pasta.  Push that into the reporting functions.

Reviewed By: ezgicicek

Differential Revision: D16859208

fbshipit-source-id: 5370efd41
master
Nikos Gorogiannis 6 years ago committed by Facebook Github Bot
parent 6bd25fd9dd
commit 1bfbdbb4e1

@ -992,7 +992,7 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
let open RacerDDomain in let open RacerDDomain in
let open RacerDModels in let open RacerDModels in
let is_duplicate_report ({snapshot; procdesc} : reported_access) let is_duplicate_report ({snapshot; procdesc} : reported_access)
{reported_sites; reported_writes; reported_reads; reported_unannotated_calls} = ({reported_sites; reported_writes; reported_reads; reported_unannotated_calls}, _) =
let pname = Procdesc.get_proc_name procdesc in let pname = Procdesc.get_proc_name procdesc in
let call_site = CallSite.make pname (TraceElem.get_loc snapshot.access) in let call_site = CallSite.make pname (TraceElem.get_loc snapshot.access) in
if Config.filtering then if Config.filtering then
@ -1026,23 +1026,35 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
{reported with reported_unannotated_calls; reported_sites} {reported with reported_unannotated_calls; reported_sites}
else reported else reported
in in
let report_unsafe_access accesses (reported_acc, issue_log) let report_thread_safety_violation ~acc ~make_description ~report_kind reported_access =
({snapshot; threads; tenv; procdesc} as reported_access) = if is_duplicate_report reported_access acc then acc
let pname = Procdesc.get_proc_name procdesc in else
if is_duplicate_report reported_access reported_acc then (reported_acc, issue_log) let reported_acc, issue_log = acc in
let issue_log =
report_thread_safety_violation ~issue_log ~make_description ~report_kind reported_access
in
(update_reported reported_access reported_acc, issue_log)
in
let report_unannotated_interface_violation ~acc reported_pname reported_access =
if is_duplicate_report reported_access acc then acc
else else
let reported_acc, issue_log = acc in
let issue_log =
report_unannotated_interface_violation ~issue_log reported_pname reported_access
in
(update_reported reported_access reported_acc, issue_log)
in
let report_unsafe_access accesses acc ({snapshot; threads; tenv; procdesc} as reported_access) =
let pname = Procdesc.get_proc_name procdesc in
match snapshot.access.elem with match snapshot.access.elem with
| Access.InterfaceCall reported_pname | Access.InterfaceCall reported_pname
when AccessSnapshot.is_unprotected snapshot when AccessSnapshot.is_unprotected snapshot
&& ThreadsDomain.is_any threads && ThreadsDomain.is_any threads
&& is_marked_thread_safe procdesc tenv -> && is_marked_thread_safe procdesc tenv ->
(* un-annotated interface call + no lock in method marked thread-safe. warn *) (* un-annotated interface call + no lock in method marked thread-safe. warn *)
let issue_log = report_unannotated_interface_violation ~acc reported_pname reported_access
report_unannotated_interface_violation ~issue_log reported_pname reported_access
in
(update_reported reported_access reported_acc, issue_log)
| Access.InterfaceCall _ -> | Access.InterfaceCall _ ->
(reported_acc, issue_log) acc
| (Access.Write _ | ContainerWrite _) when Typ.Procname.is_java pname -> | (Access.Write _ | ContainerWrite _) when Typ.Procname.is_java pname ->
let conflict = let conflict =
if ThreadsDomain.is_any threads then if ThreadsDomain.is_any threads then
@ -1061,16 +1073,12 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
AccessSnapshot.is_unprotected snapshot AccessSnapshot.is_unprotected snapshot
&& (Option.is_some conflict || ThreadsDomain.is_any threads) && (Option.is_some conflict || ThreadsDomain.is_any threads)
then then
let issue_log = report_thread_safety_violation ~acc ~make_description:make_unprotected_write_description
report_thread_safety_violation ~issue_log
~make_description:make_unprotected_write_description
~report_kind:(WriteWriteRace conflict) reported_access ~report_kind:(WriteWriteRace conflict) reported_access
in else acc
(update_reported reported_access reported_acc, issue_log)
else (reported_acc, issue_log)
| Access.Write _ | ContainerWrite _ -> | Access.Write _ | ContainerWrite _ ->
(* Do not report unprotected writes for ObjC_Cpp *) (* Do not report unprotected writes for ObjC_Cpp *)
(reported_acc, issue_log) acc
| (Access.Read _ | ContainerRead _) when AccessSnapshot.is_unprotected snapshot -> | (Access.Read _ | ContainerRead _) when AccessSnapshot.is_unprotected snapshot ->
(* unprotected read. report all writes as conflicts for java. for c++ filter out (* unprotected read. report all writes as conflicts for java. for c++ filter out
unprotected writes *) unprotected writes *)
@ -1082,16 +1090,13 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
else not (AccessSnapshot.is_unprotected snapshot) else not (AccessSnapshot.is_unprotected snapshot)
in in
List.find ~f:is_conflict accesses List.find ~f:is_conflict accesses
|> Option.value_map ~default:(reported_acc, issue_log) ~f:(fun conflict -> |> Option.value_map ~default:acc ~f:(fun conflict ->
let make_description = let make_description =
make_read_write_race_description ~read_is_sync:false conflict make_read_write_race_description ~read_is_sync:false conflict
in in
let report_kind = ReadWriteRace conflict.snapshot.access in let report_kind = ReadWriteRace conflict.snapshot.access in
let issue_log = report_thread_safety_violation ~acc ~make_description ~report_kind reported_access
report_thread_safety_violation ~issue_log ~make_description ~report_kind )
reported_access
in
(update_reported reported_access reported_acc, issue_log) )
| Access.Read _ | ContainerRead _ -> | Access.Read _ | ContainerRead _ ->
(* protected read. report unprotected writes and opposite protected writes as conflicts *) (* protected read. report unprotected writes and opposite protected writes as conflicts *)
let can_conflict (snapshot1 : AccessSnapshot.t) (snapshot2 : AccessSnapshot.t) = let can_conflict (snapshot1 : AccessSnapshot.t) (snapshot2 : AccessSnapshot.t) =
@ -1104,17 +1109,14 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
else TraceElem.is_write other_snapshot.access && can_conflict snapshot other_snapshot else TraceElem.is_write other_snapshot.access && can_conflict snapshot other_snapshot
in in
List.find accesses ~f:is_conflict List.find accesses ~f:is_conflict
|> Option.value_map ~default:(reported_acc, issue_log) ~f:(fun conflict -> |> Option.value_map ~default:acc ~f:(fun conflict ->
(* protected read with conflicting unprotected write(s). warn. *) (* protected read with conflicting unprotected write(s). warn. *)
let make_description = let make_description =
make_read_write_race_description ~read_is_sync:true conflict make_read_write_race_description ~read_is_sync:true conflict
in in
let report_kind = ReadWriteRace conflict.snapshot.access in let report_kind = ReadWriteRace conflict.snapshot.access in
let issue_log = report_thread_safety_violation ~acc ~make_description ~report_kind reported_access
report_thread_safety_violation ~issue_log ~make_description ~report_kind )
reported_access
in
(update_reported reported_access reported_acc, issue_log) )
in in
let report_accesses_on_location reportable_accesses init = let report_accesses_on_location reportable_accesses init =
(* Don't report on location if all accesses are on non-concurrent contexts *) (* Don't report on location if all accesses are on non-concurrent contexts *)
@ -1126,14 +1128,11 @@ let report_unsafe_accesses ~issue_log classname (aggregated_access_map : ReportM
in in
let report_guardedby_violations_on_location grouped_accesses init = let report_guardedby_violations_on_location grouped_accesses init =
if Config.racerd_guardedby then if Config.racerd_guardedby then
List.fold grouped_accesses ~init ~f:(fun (acc, issue_log) r -> List.fold grouped_accesses ~init ~f:(fun acc r ->
if should_report_guardedby_violation classname r && not (is_duplicate_report r acc) then if should_report_guardedby_violation classname r then
let issue_log = report_thread_safety_violation ~acc ~report_kind:GuardedByViolation
report_thread_safety_violation ~issue_log ~report_kind:GuardedByViolation
~make_description:make_guardedby_violation_description r ~make_description:make_guardedby_violation_description r
in else acc )
(update_reported r acc, issue_log)
else (acc, issue_log) )
else init else init
in in
let report grouped_accesses (reported, issue_log) = let report grouped_accesses (reported, issue_log) =

Loading…
Cancel
Save