|
|
@ -1254,31 +1254,20 @@ let report_unsafe_accesses (aggregated_access_map : ReportMap.t) =
|
|
|
|
{ reported_acc with
|
|
|
|
{ reported_acc with
|
|
|
|
reported_writes= Typ.Procname.Set.empty; reported_reads= Typ.Procname.Set.empty }
|
|
|
|
reported_writes= Typ.Procname.Set.empty; reported_reads= Typ.Procname.Set.empty }
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let class_has_mutex_member objc_cpp tenv =
|
|
|
|
|
|
|
|
let class_name = Typ.Procname.ObjC_Cpp.get_class_type_name objc_cpp in
|
|
|
|
|
|
|
|
let matcher = ConcurrencyModels.cpp_lock_types_matcher in
|
|
|
|
|
|
|
|
Option.exists (Tenv.lookup tenv class_name) ~f:(fun class_str ->
|
|
|
|
|
|
|
|
(* check if the class contains a lock member *)
|
|
|
|
|
|
|
|
List.exists class_str.Typ.Struct.fields ~f:(fun (_, ft, _) ->
|
|
|
|
|
|
|
|
Option.exists (Typ.name ft) ~f:(fun name ->
|
|
|
|
|
|
|
|
QualifiedCppName.Match.match_qualifiers matcher (Typ.Name.qual_name name) ) ) )
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
let should_report {tenv; procdesc} =
|
|
|
|
let should_report {tenv; procdesc} =
|
|
|
|
|
|
|
|
List.exists grouped_accesses ~f:(fun ({threads} : reported_access) ->
|
|
|
|
|
|
|
|
ThreadsDomain.is_any threads )
|
|
|
|
|
|
|
|
&&
|
|
|
|
match Procdesc.get_proc_name procdesc with
|
|
|
|
match Procdesc.get_proc_name procdesc with
|
|
|
|
| Java _ ->
|
|
|
|
| Java _ ->
|
|
|
|
List.exists grouped_accesses ~f:(fun ({threads} : reported_access) ->
|
|
|
|
should_report_in_java procdesc tenv
|
|
|
|
ThreadsDomain.is_any threads )
|
|
|
|
|
|
|
|
&& should_report_on_proc procdesc tenv
|
|
|
|
|
|
|
|
| ObjC_Cpp objc_cpp ->
|
|
|
|
| ObjC_Cpp objc_cpp ->
|
|
|
|
(* do not report if a procedure is private *)
|
|
|
|
should_report_in_objcpp procdesc objc_cpp tenv
|
|
|
|
Procdesc.get_access procdesc <> PredSymb.Private
|
|
|
|
|
|
|
|
&& (* report if the class has a mutex member *)
|
|
|
|
|
|
|
|
class_has_mutex_member objc_cpp tenv
|
|
|
|
|
|
|
|
| _ ->
|
|
|
|
| _ ->
|
|
|
|
false
|
|
|
|
false
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let reportable_accesses = List.filter ~f:should_report grouped_accesses in
|
|
|
|
let reportable_accesses = List.filter ~f:should_report grouped_accesses in
|
|
|
|
List.fold ~f:(report_unsafe_access reportable_accesses) reportable_accesses ~init:reported
|
|
|
|
List.fold reportable_accesses ~init:reported ~f:(report_unsafe_access reportable_accesses)
|
|
|
|
in
|
|
|
|
in
|
|
|
|
ReportMap.fold report_accesses_on_location aggregated_access_map empty_reported |> ignore
|
|
|
|
ReportMap.fold report_accesses_on_location aggregated_access_map empty_reported |> ignore
|
|
|
|
|
|
|
|
|
|
|
@ -1291,43 +1280,37 @@ let make_results_table file_env =
|
|
|
|
let open RacerDDomain in
|
|
|
|
let open RacerDDomain in
|
|
|
|
let aggregate_post tenv procdesc acc {threads; accesses; wobbly_paths} =
|
|
|
|
let aggregate_post tenv procdesc acc {threads; accesses; wobbly_paths} =
|
|
|
|
AccessDomain.fold
|
|
|
|
AccessDomain.fold
|
|
|
|
(fun snapshot acc ->
|
|
|
|
(fun snapshot acc -> ReportMap.add {threads; snapshot; tenv; procdesc; wobbly_paths} acc)
|
|
|
|
let reported_access : reported_access =
|
|
|
|
|
|
|
|
{threads; snapshot; tenv; procdesc; wobbly_paths}
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
ReportMap.add reported_access acc )
|
|
|
|
|
|
|
|
accesses acc
|
|
|
|
accesses acc
|
|
|
|
in
|
|
|
|
in
|
|
|
|
let aggregate_posts acc (tenv, proc_desc) =
|
|
|
|
let aggregate_posts acc (tenv, proc_desc) =
|
|
|
|
Payload.read proc_desc (Procdesc.get_proc_name proc_desc)
|
|
|
|
Payload.read proc_desc (Procdesc.get_proc_name proc_desc)
|
|
|
|
|> Option.fold ~init:acc ~f:(aggregate_post tenv proc_desc)
|
|
|
|
|> Option.fold ~init:acc ~f:(aggregate_post tenv proc_desc)
|
|
|
|
in
|
|
|
|
in
|
|
|
|
List.fold ~f:aggregate_posts file_env ~init:ReportMap.empty
|
|
|
|
List.fold file_env ~init:ReportMap.empty ~f:aggregate_posts
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(* aggregate all of the procedures in the file env by their declaring
|
|
|
|
(* aggregate all of the procedures in the file env by their declaring
|
|
|
|
class. this lets us analyze each class individually *)
|
|
|
|
class. this lets us analyze each class individually *)
|
|
|
|
let aggregate_by_class file_env =
|
|
|
|
let aggregate_by_class file_env =
|
|
|
|
List.fold file_env
|
|
|
|
List.fold file_env ~init:String.Map.empty ~f:(fun acc ((_, pdesc) as proc) ->
|
|
|
|
~f:(fun acc ((_, pdesc) as proc) ->
|
|
|
|
|
|
|
|
let pname = Procdesc.get_proc_name pdesc in
|
|
|
|
|
|
|
|
let classname =
|
|
|
|
let classname =
|
|
|
|
match pname with
|
|
|
|
match Procdesc.get_proc_name pdesc with
|
|
|
|
| Typ.Procname.Java java_pname ->
|
|
|
|
| Typ.Procname.Java java_pname ->
|
|
|
|
Typ.Procname.Java.get_class_name java_pname
|
|
|
|
Some (Typ.Procname.Java.get_class_name java_pname)
|
|
|
|
|
|
|
|
| ObjC_Cpp objc_cpp_pname ->
|
|
|
|
|
|
|
|
Some (Typ.Procname.ObjC_Cpp.get_class_name objc_cpp_pname)
|
|
|
|
| _ ->
|
|
|
|
| _ ->
|
|
|
|
"unknown"
|
|
|
|
None
|
|
|
|
in
|
|
|
|
in
|
|
|
|
String.Map.update acc classname ~f:(function None -> [proc] | Some bucket -> proc :: bucket)
|
|
|
|
Option.fold classname ~init:acc ~f:(fun acc classname ->
|
|
|
|
)
|
|
|
|
String.Map.add_multi acc ~key:classname ~data:proc ) )
|
|
|
|
~init:String.Map.empty
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(* Gathers results by analyzing all the methods in a file, then
|
|
|
|
(* Gathers results by analyzing all the methods in a file, then
|
|
|
|
post-processes the results to check an (approximation of) thread
|
|
|
|
post-processes the results to check an (approximation of) thread
|
|
|
|
safety *)
|
|
|
|
safety *)
|
|
|
|
let file_analysis {Callbacks.procedures; source_file} =
|
|
|
|
let file_analysis {Callbacks.procedures; source_file} =
|
|
|
|
String.Map.iter
|
|
|
|
String.Map.iter (aggregate_by_class procedures) ~f:(fun class_env ->
|
|
|
|
~f:(fun class_env -> report_unsafe_accesses (make_results_table class_env))
|
|
|
|
report_unsafe_accesses (make_results_table class_env) ) ;
|
|
|
|
(aggregate_by_class procedures) ;
|
|
|
|
|
|
|
|
IssueLog.store Config.racerd_issues_dir_name source_file
|
|
|
|
IssueLog.store Config.racerd_issues_dir_name source_file
|
|
|
|