@ -38,10 +38,11 @@ let init_fields_zero tenv path location ~zero addr typ astate =
(* * Constructs summary [{self = 0} {return = self}] when [proc_desc] returns a POD type. This allows
(* * Constructs summary [{self = 0} {return = self}] when [proc_desc] returns a POD type. This allows
us to connect invalidation with invalid access in the trace * )
us to connect invalidation with invalid access in the trace * )
let mk_ objc_method_nil_summary_aux tenv proc_desc astate =
let mk_ nil_messaging_summary_aux tenv proc_desc =
let path = PathContext . initial in
let path = PathContext . initial in
let location = Procdesc . get_loc proc_desc in
let location = Procdesc . get_loc proc_desc in
let self = mk_objc_self_pvar proc_desc in
let self = mk_objc_self_pvar proc_desc in
let astate = AbductiveDomain . mk_initial tenv proc_desc in
(* HACK: we are operating on an "empty" initial state and do not expect to create any alarms
(* HACK: we are operating on an "empty" initial state and do not expect to create any alarms
( nothing is Invalid in the initial state ) or unsatisfiability ( we won't create arithmetic
( nothing is Invalid in the initial state ) or unsatisfiability ( we won't create arithmetic
contradictions ) * )
contradictions ) * )
@ -71,12 +72,13 @@ let mk_objc_method_nil_summary_aux tenv proc_desc astate =
| > assert_ok
| > assert_ok
let mk_objc_latent_non_POD_nil_messaging tenv proc_desc astate =
let mk_latent_non_POD_nil_messaging tenv proc_desc =
(* same HACK as above *)
let assert_ok = function Ok x -> x | Error _ -> assert false in
let path = PathContext . initial in
let path = PathContext . initial in
let location = Procdesc . get_loc proc_desc in
let location = Procdesc . get_loc proc_desc in
let self = mk_objc_self_pvar proc_desc in
let self = mk_objc_self_pvar proc_desc in
let astate = AbductiveDomain . mk_initial tenv proc_desc in
(* same HACK as above *)
let assert_ok = function Ok x -> x | Error _ -> assert false in
let astate , ( self_value , _ self_history ) =
let astate , ( self_value , _ self_history ) =
PulseOperations . eval_deref path location ( Lvar self ) astate | > assert_ok
PulseOperations . eval_deref path location ( Lvar self ) astate | > assert_ok
in
in
@ -94,50 +96,41 @@ let mk_objc_latent_non_POD_nil_messaging tenv proc_desc astate =
; calling_context = [] }
; calling_context = [] }
let mk_ objc_method_nil_summary tenv proc_desc initial =
let mk_ nil_messaging_summary tenv proc_desc =
let proc_name = Procdesc . get_proc_name proc_desc in
let proc_name = Procdesc . get_proc_name proc_desc in
match ( initial , proc_name ) with
match proc_name with
| ContinueProgram astate , Procname . ObjC_Cpp { kind = ObjCInstanceMethod } ->
| Procname . ObjC_Cpp { kind = ObjCInstanceMethod } ->
if Procdesc . is_ret_type_pod proc_desc then
if Procdesc . is_ret_type_pod proc_desc then
(* In ObjC, when a method is called on nil, there is no NPE,
(* In ObjC, when a method is called on nil, there is no NPE,
the method is actually not called and the return value is 0 / false / nil .
the method is actually not called and the return value is 0 / false / nil .
We create a nil summary to avoid reporting NPE in this case .
We create a nil summary to avoid reporting NPE in this case .
However , there is an exception in the case where the return type is non - POD .
However , there is an exception in the case where the return type is non - POD .
In that case it's UB and we want to report an error . * )
In that case it's UB and we want to report an error . * )
let astate = mk_ objc_method_nil_summary_aux tenv proc_desc astate in
let astate = mk_ nil_messaging_summary_aux tenv proc_desc in
Some ( ContinueProgram astate )
Some ( ContinueProgram astate )
else
else
let summary = mk_ objc_ latent_non_POD_nil_messaging tenv proc_desc astate in
let summary = mk_ latent_non_POD_nil_messaging tenv proc_desc in
Some summary
Some summary
| ContinueProgram _ , _
| _ ->
| ExitProgram _ , _
| AbortProgram _ , _
| LatentAbortProgram _ , _
| LatentInvalidAccess _ , _
| ISLLatentMemoryError _ , _ ->
None
None
let append_objc_self_positive { InterproceduralAnalysis . tenv ; proc_desc ; err_log } astate =
let mk_initial_with_positive_self tenv proc_desc =
let location = Procdesc . get_loc proc_desc in
let location = Procdesc . get_loc proc_desc in
let self = mk_objc_self_pvar proc_desc in
let self = mk_objc_self_pvar proc_desc in
let proc_name = Procdesc . get_proc_name proc_desc in
let proc_name = Procdesc . get_proc_name proc_desc in
match ( astate , proc_name ) with
let initial_astate = AbductiveDomain . mk_initial tenv proc_desc in
| ContinueProgram astate , Procname . ObjC_Cpp { kind = ObjCInstanceMethod } ->
(* same HACK as above *)
let result =
let assert_ok = function Ok x -> x | Error _ -> assert false in
let * astate , value =
match proc_name with
PulseOperations . eval_deref PathContext . initial location ( Lvar self ) astate
| Procname . ObjC_Cpp { kind = ObjCInstanceMethod } ->
in
let astate , value =
PulseArithmetic . and_positive ( fst value ) astate
PulseOperations . eval_deref PathContext . initial location ( Lvar self ) initial_astate
| > assert_ok
in
in
PulseReport . report_result tenv proc_desc err_log location result
PulseArithmetic . and_positive ( fst value ) astate | > assert_ok
| ContinueProgram _ , _
| _ ->
| ExitProgram _ , _
initial_astate
| AbortProgram _ , _
| LatentAbortProgram _ , _
| LatentInvalidAccess _ , _
| ISLLatentMemoryError _ , _ ->
[ astate ]
let append_objc_actual_self_positive procdesc self_actual astate =
let append_objc_actual_self_positive procdesc self_actual astate =
@ -148,11 +141,3 @@ let append_objc_actual_self_positive procdesc self_actual astate =
PulseArithmetic . prune_positive self astate )
PulseArithmetic . prune_positive self astate )
| _ ->
| _ ->
Ok astate
Ok astate
let update_objc_method_posts { InterproceduralAnalysis . tenv ; proc_desc } ~ initial_astate ~ posts =
match mk_objc_method_nil_summary tenv proc_desc initial_astate with
| None ->
posts
| Some nil_summary ->
nil_summary :: posts