@ -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 ) =