nullifying vars captured in blocks

Reviewed By: ddino

Differential Revision: D3072561

fb-gh-sync-id: 60925b0
fbshipit-source-id: 60925b0
master
Sam Blackshear 9 years ago committed by Facebook Github Bot 8
parent f1b68fe5b9
commit 7166a4856c

@ -48,29 +48,23 @@ end
module Vset = AddressTaken.PvarSet module Vset = AddressTaken.PvarSet
let captured_var = ref Vset.empty
let is_not_function cfg x = let is_not_function cfg x =
let pname = Procname.from_string_c_fun (Mangled.to_string (Pvar.get_name x)) in let pname = Procname.from_string_c_fun (Mangled.to_string (Pvar.get_name x)) in
Cfg.Procdesc.find_from_name cfg pname = None Cfg.Procdesc.find_from_name cfg pname = None
let is_captured pdesc x =
let captured = Cfg.Procdesc.get_captured pdesc in
IList.exists (fun (m, _) -> (Pvar.to_string x) = (Mangled.to_string m)) captured
(** variables read in the expression *) (** variables read in the expression *)
let rec use_exp cfg pdesc (exp: Sil.exp) acc = let rec use_exp cfg pdesc (exp: Sil.exp) acc =
match exp with match exp with
| Sil.Var _ | Sil.Sizeof _ -> acc | Sil.Var _ | Sil.Sizeof _ -> acc
| Sil.Const (Cclosure { captured_vars }) -> | Sil.Const (Cclosure { captured_vars; }) ->
IList.iter IList.fold_left
(fun (_, captured, _) -> captured_var:= Vset.add captured !captured_var) (fun vset_acc (_, captured_pvar, _) -> Vset.add captured_pvar vset_acc)
captured_vars; acc
captured_vars
| Sil.Const
(Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cattribute _ | Cexn _ | Cclass _ | Cptr_to_fld _) ->
acc acc
| Sil.Const _ -> acc | Sil.Lvar x -> Vset.add x acc
| Sil.Lvar x ->
(* If x is a captured var in the current procdesc don't add it to acc *)
if is_captured pdesc x then acc else Vset.add x acc
| Sil.Cast (_, e) | Sil.UnOp (_, e, _) | Sil.Lfield (e, _, _) -> use_exp cfg pdesc e acc | Sil.Cast (_, e) | Sil.UnOp (_, e, _) | Sil.Lfield (e, _, _) -> use_exp cfg pdesc e acc
| Sil.BinOp (_, e1, e2) | Sil.Lindex (e1, e2) -> use_exp cfg pdesc e1 (use_exp cfg pdesc e2 acc) | Sil.BinOp (_, e1, e2) | Sil.Lindex (e1, e2) -> use_exp cfg pdesc e1 (use_exp cfg pdesc e2 acc)
@ -179,12 +173,8 @@ let compute_candidates procdesc : Vset.t * (Vset.t -> Vset.elt list) =
| _ -> false in | _ -> false in
let add_vi (pvar, typ) = let add_vi (pvar, typ) =
let pv = Pvar.mk pvar (Cfg.Procdesc.get_proc_name procdesc) in let pv = Pvar.mk pvar (Cfg.Procdesc.get_proc_name procdesc) in
if is_captured procdesc pv then () candidates := Vset.add pv !candidates;
(* don't add captured vars of the current pdesc to candidates *) if typ_is_struct_array typ then struct_array_cand := Vset.add pv !struct_array_cand in
else (
candidates := Vset.add pv !candidates;
if typ_is_struct_array typ then struct_array_cand := Vset.add pv !struct_array_cand
) in
IList.iter add_vi (Cfg.Procdesc.get_formals procdesc); IList.iter add_vi (Cfg.Procdesc.get_formals procdesc);
IList.iter add_vi (Cfg.Procdesc.get_locals procdesc); IList.iter add_vi (Cfg.Procdesc.get_locals procdesc);
let get_sorted_candidates vs = let get_sorted_candidates vs =
@ -306,7 +296,6 @@ let analyze_and_annotate_proc cfg pname pdesc =
match AddressTaken.Analyzer.compute_post pdesc with match AddressTaken.Analyzer.compute_post pdesc with
| Some post -> post | Some post -> post
| None -> Vset.empty in | None -> Vset.empty in
captured_var:= Vset.empty;
analyze_proc cfg pdesc cand; analyze_proc cfg pdesc cand;
@ -321,13 +310,11 @@ let analyze_and_annotate_proc cfg pname pdesc =
L.err "WARNING: liveness: more than %d dead pvars added in procedure %a, stopping@." L.err "WARNING: liveness: more than %d dead pvars added in procedure %a, stopping@."
dead_pvars_limit Procname.pp pname in dead_pvars_limit Procname.pp pname in
Table.iter cand (fun n live_at_predecessors live_current -> (* set dead variables on nodes *) Table.iter cand (fun n live_at_predecessors live_current -> (* set dead variables on nodes *)
let nonnull_pvars = (* live before, or assigned to *)
Vset.inter (def_node cfg n live_at_predecessors) cand in (* live before, or assigned to *) let nonnull_pvars = Vset.inter (def_node cfg n live_at_predecessors) cand in
let dead_pvars = (* only nullify when variables become live *)
Vset.diff nonnull_pvars live_current in (* only nullify when variable become live *) let dead_pvars = Vset.diff nonnull_pvars live_current in
let dead_pvars_no_captured = Vset.diff dead_pvars !captured_var in let dead_pvars_no_addr_taken = get_sorted_cand (Vset.diff dead_pvars addr_taken_vars) in
let dead_pvars_no_addr_taken =
get_sorted_cand (Vset.diff dead_pvars_no_captured addr_taken_vars) in
let dead_pvars_to_add = let dead_pvars_to_add =
if exit_node_is_succ n (* add dead address taken vars just before the exit node *) if exit_node_is_succ n (* add dead address taken vars just before the exit node *)
then dead_pvars_no_addr_taken @ (get_sorted_cand (Vset.inter cand addr_taken_vars)) then dead_pvars_no_addr_taken @ (get_sorted_cand (Vset.inter cand addr_taken_vars))

@ -1,143 +1,238 @@
digraph iCFG { digraph iCFG {
50 [label="50: DeclStmt \n n$35=_fun_FBColorCreateWithGray(0.000000:double ,0.300000:double ) [line 86]\n *&borderColor:struct CGColor *=n$35 [line 86]\n REMOVE_TEMPS(n$35); [line 86]\n " shape="box"] 75 [label="75: DeclStmt \n n$59=_fun_malloc_no_fail(sizeof(int ):int ) [line 103]\n *&x:int *=n$59 [line 103]\n REMOVE_TEMPS(n$59); [line 103]\n " shape="box"]
75 -> 74 ;
74 [label="74: BinaryOperatorStmt: Assign \n n$58=*&x:int * [line 104]\n *n$58:int =2 [line 104]\n REMOVE_TEMPS(n$58); [line 104]\n " shape="box"]
74 -> 73 ;
73 [label="73: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2); [line 105]\n n$56=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2 ):unsigned long ) [line 105]\n *&__objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2:class __objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2 =n$56 [line 105]\n n$57=*&x:int * [line 105]\n *n$56.x:int *=n$57 [line 105]\n n$51=*&x:int * [line 105]\n *&blk:_fn_ (*)=(_fun___objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2,n$51) [line 105]\n REMOVE_TEMPS(n$56,n$57,n$51); [line 105]\n NULLIFY(&x,false); [line 105]\n " shape="box"]
73 -> 67 ;
72 [label="72: DeclStmt \n n$54=*&x:int * [line 106]\n n$55=*n$54:int [line 106]\n *&i:int =n$55 [line 106]\n REMOVE_TEMPS(n$54,n$55); [line 106]\n " shape="box"]
72 -> 71 ;
71 [label="71: Call _fun_free \n n$53=*&x:int * [line 107]\n _fun_free(n$53:void *) [line 107]\n REMOVE_TEMPS(n$53); [line 107]\n NULLIFY(&x,false); [line 107]\n " shape="box"]
71 -> 70 ;
70 [label="70: Return Stmt \n n$52=*&i:int [line 108]\n *&return:int =n$52 [line 108]\n REMOVE_TEMPS(n$52); [line 108]\n NULLIFY(&i,false); [line 108]\n APPLY_ABSTRACTION; [line 108]\n " shape="box"]
70 -> 69 ;
69 [label="69: Exit __objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2 \n " color=yellow style=filled]
68 [label="68: Start __objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2\nFormals: x:int *\nLocals: i:int \nCaptured: x:int * \n DECLARE_LOCALS(&return,&i); [line 105]\n NULLIFY(&i,false); [line 105]\n " color=yellow style=filled]
68 -> 72 ;
67 [label="67: Return Stmt \n n$49=*&blk:_fn_ (*) [line 110]\n n$50=n$49() [line 110]\n *&return:int =n$50 [line 110]\n REMOVE_TEMPS(n$49,n$50); [line 110]\n NULLIFY(&__objc_anonymous_block_MemoryLeakExample_blockFreeNoLeakTODO______2,true); [line 110]\n NULLIFY(&blk,false); [line 110]\n APPLY_ABSTRACTION; [line 110]\n " shape="box"]
67 -> 66 ;
66 [label="66: Exit MemoryLeakExample_blockFreeNoLeakTODO \n " color=yellow style=filled]
65 [label="65: Start MemoryLeakExample_blockFreeNoLeakTODO\nFormals: self:class MemoryLeakExample *\nLocals: blk:_fn_ (*) x:int * \n DECLARE_LOCALS(&return,&blk,&x); [line 102]\n NULLIFY(&blk,false); [line 102]\n NULLIFY(&self,false); [line 102]\n NULLIFY(&x,false); [line 102]\n " color=yellow style=filled]
65 -> 75 ;
64 [label="64: DeclStmt \n n$48=_fun_malloc_no_fail(sizeof(int ):int ) [line 94]\n *&x:int *=n$48 [line 94]\n REMOVE_TEMPS(n$48); [line 94]\n " shape="box"]
64 -> 63 ;
63 [label="63: BinaryOperatorStmt: Assign \n n$47=*&x:int * [line 95]\n *n$47:int =2 [line 95]\n REMOVE_TEMPS(n$47); [line 95]\n " shape="box"]
63 -> 62 ;
62 [label="62: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1); [line 96]\n n$45=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1 ):unsigned long ) [line 96]\n *&__objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1:class __objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1 =n$45 [line 96]\n n$46=*&x:int * [line 96]\n *n$45.x:int *=n$46 [line 96]\n n$42=*&x:int * [line 96]\n *&blk:_fn_ (*)=(_fun___objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1,n$42) [line 96]\n REMOVE_TEMPS(n$45,n$46,n$42); [line 96]\n NULLIFY(&x,false); [line 96]\n " shape="box"]
62 -> 58 ;
61 [label="61: Return Stmt \n n$43=*&x:int * [line 97]\n n$44=*n$43:int [line 97]\n *&return:int =n$44 [line 97]\n REMOVE_TEMPS(n$43,n$44); [line 97]\n NULLIFY(&x,false); [line 97]\n APPLY_ABSTRACTION; [line 97]\n " shape="box"]
61 -> 60 ;
60 [label="60: Exit __objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1 \n " color=yellow style=filled]
59 [label="59: Start __objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1\nFormals: x:int *\nLocals: \nCaptured: x:int * \n DECLARE_LOCALS(&return); [line 96]\n " color=yellow style=filled]
59 -> 61 ;
58 [label="58: Return Stmt \n n$40=*&blk:_fn_ (*) [line 99]\n n$41=n$40() [line 99]\n *&return:int =n$41 [line 99]\n REMOVE_TEMPS(n$40,n$41); [line 99]\n NULLIFY(&__objc_anonymous_block_MemoryLeakExample_blockCapturedVarLeak______1,true); [line 99]\n NULLIFY(&blk,false); [line 99]\n APPLY_ABSTRACTION; [line 99]\n " shape="box"]
58 -> 57 ;
57 [label="57: Exit MemoryLeakExample_blockCapturedVarLeak \n " color=yellow style=filled]
56 [label="56: Start MemoryLeakExample_blockCapturedVarLeak\nFormals: self:class MemoryLeakExample *\nLocals: blk:_fn_ (*) x:int * \n DECLARE_LOCALS(&return,&blk,&x); [line 93]\n NULLIFY(&blk,false); [line 93]\n NULLIFY(&self,false); [line 93]\n NULLIFY(&x,false); [line 93]\n " color=yellow style=filled]
56 -> 64 ;
55 [label="55: DeclStmt \n n$39=_fun_malloc_no_fail(sizeof(int ):int ) [line 88]\n *&x:int *=n$39 [line 88]\n REMOVE_TEMPS(n$39); [line 88]\n " shape="box"]
55 -> 54 ;
54 [label="54: BinaryOperatorStmt: Assign \n n$38=*&x:int * [line 89]\n *n$38:int =7 [line 89]\n REMOVE_TEMPS(n$38); [line 89]\n " shape="box"]
54 -> 53 ;
53 [label="53: Return Stmt \n n$36=*&x:int * [line 90]\n n$37=*n$36:int [line 90]\n *&return:int =n$37 [line 90]\n REMOVE_TEMPS(n$36,n$37); [line 90]\n NULLIFY(&x,false); [line 90]\n APPLY_ABSTRACTION; [line 90]\n " shape="box"]
53 -> 52 ;
52 [label="52: Exit MemoryLeakExample_regularLeak \n " color=yellow style=filled]
51 [label="51: Start MemoryLeakExample_regularLeak\nFormals: self:class MemoryLeakExample *\nLocals: x:int * \n DECLARE_LOCALS(&return,&x); [line 87]\n NULLIFY(&self,false); [line 87]\n NULLIFY(&x,false); [line 87]\n " color=yellow style=filled]
51 -> 55 ;
50 [label="50: DeclStmt \n n$35=_fun_FBColorCreateWithGray(0.000000:double ,0.300000:double ) [line 83]\n *&borderColor:struct CGColor *=n$35 [line 83]\n REMOVE_TEMPS(n$35); [line 83]\n " shape="box"]
50 -> 49 ; 50 -> 49 ;
49 [label="49: Call _fun_CGColorRelease \n n$34=*&borderColor:struct CGColor * [line 87]\n _fun_CGColorRelease(n$34:struct CGColor *) [line 87]\n REMOVE_TEMPS(n$34); [line 87]\n NULLIFY(&borderColor,false); [line 87]\n APPLY_ABSTRACTION; [line 87]\n " shape="box"] 49 [label="49: Call _fun_CGColorRelease \n n$34=*&borderColor:struct CGColor * [line 84]\n _fun_CGColorRelease(n$34:struct CGColor *) [line 84]\n REMOVE_TEMPS(n$34); [line 84]\n NULLIFY(&borderColor,false); [line 84]\n APPLY_ABSTRACTION; [line 84]\n " shape="box"]
49 -> 48 ; 49 -> 48 ;
48 [label="48: Exit MemoryLeakExample_testFBColorCreateWithGray \n " color=yellow style=filled] 48 [label="48: Exit MemoryLeakExample_testFBColorCreateWithGray \n " color=yellow style=filled]
47 [label="47: Start MemoryLeakExample_testFBColorCreateWithGray\nFormals: self:class MemoryLeakExample *\nLocals: borderColor:struct CGColor * \n DECLARE_LOCALS(&return,&borderColor); [line 85]\n NULLIFY(&borderColor,false); [line 85]\n NULLIFY(&self,false); [line 85]\n " color=yellow style=filled] 47 [label="47: Start MemoryLeakExample_testFBColorCreateWithGray\nFormals: self:class MemoryLeakExample *\nLocals: borderColor:struct CGColor * \n DECLARE_LOCALS(&return,&borderColor); [line 82]\n NULLIFY(&borderColor,false); [line 82]\n NULLIFY(&self,false); [line 82]\n " color=yellow style=filled]
47 -> 50 ; 47 -> 50 ;
46 [label="46: DeclStmt \n n$33=_fun_CGBitmapContextCreateImage(0:struct CGContext *) [line 79]\n *&newImage:struct CGImage *=n$33 [line 79]\n REMOVE_TEMPS(n$33); [line 79]\n " shape="box"] 46 [label="46: DeclStmt \n n$33=_fun_CGBitmapContextCreateImage(0:struct CGContext *) [line 76]\n *&newImage:struct CGImage *=n$33 [line 76]\n REMOVE_TEMPS(n$33); [line 76]\n " shape="box"]
46 -> 45 ; 46 -> 45 ;
45 [label="45: Call _fun_CGImageRelease \n n$32=*&newImage:struct CGImage * [line 80]\n _fun_CGImageRelease(n$32:struct CGImage *) [line 80]\n REMOVE_TEMPS(n$32); [line 80]\n NULLIFY(&newImage,false); [line 80]\n APPLY_ABSTRACTION; [line 80]\n " shape="box"] 45 [label="45: Call _fun_CGImageRelease \n n$32=*&newImage:struct CGImage * [line 77]\n _fun_CGImageRelease(n$32:struct CGImage *) [line 77]\n REMOVE_TEMPS(n$32); [line 77]\n NULLIFY(&newImage,false); [line 77]\n APPLY_ABSTRACTION; [line 77]\n " shape="box"]
45 -> 44 ; 45 -> 44 ;
44 [label="44: Exit MemoryLeakExample_testImageRefRelease \n " color=yellow style=filled] 44 [label="44: Exit MemoryLeakExample_testImageRefRelease \n " color=yellow style=filled]
43 [label="43: Start MemoryLeakExample_testImageRefRelease\nFormals: \nLocals: newImage:struct CGImage * \n DECLARE_LOCALS(&return,&newImage); [line 78]\n NULLIFY(&newImage,false); [line 78]\n " color=yellow style=filled] 43 [label="43: Start MemoryLeakExample_testImageRefRelease\nFormals: \nLocals: newImage:struct CGImage * \n DECLARE_LOCALS(&return,&newImage); [line 75]\n NULLIFY(&newImage,false); [line 75]\n " color=yellow style=filled]
43 -> 46 ; 43 -> 46 ;
42 [label="42: DeclStmt \n n$31=_fun_SecTrustCopyPublicKey(0:struct __SecTrust *) [line 74]\n *&allowedPublicKey:struct __SecKey *=n$31 [line 74]\n REMOVE_TEMPS(n$31); [line 74]\n " shape="box"] 42 [label="42: DeclStmt \n n$31=_fun_SecTrustCopyPublicKey(0:struct __SecTrust *) [line 71]\n *&allowedPublicKey:struct __SecKey *=n$31 [line 71]\n REMOVE_TEMPS(n$31); [line 71]\n " shape="box"]
42 -> 41 ; 42 -> 41 ;
41 [label="41: Call _fun___objc_release_cf \n n$30=*&allowedPublicKey:struct __SecKey * [line 75]\n _fun___objc_release_cf(1:_Bool ,n$30:void *) [line 75]\n REMOVE_TEMPS(n$30); [line 75]\n NULLIFY(&allowedPublicKey,false); [line 75]\n APPLY_ABSTRACTION; [line 75]\n " shape="box"] 41 [label="41: Call _fun___objc_release_cf \n n$30=*&allowedPublicKey:struct __SecKey * [line 72]\n _fun___objc_release_cf(1:_Bool ,n$30:void *) [line 72]\n REMOVE_TEMPS(n$30); [line 72]\n NULLIFY(&allowedPublicKey,false); [line 72]\n APPLY_ABSTRACTION; [line 72]\n " shape="box"]
41 -> 40 ; 41 -> 40 ;
40 [label="40: Exit MemoryLeakExample_test2NoLeak \n " color=yellow style=filled] 40 [label="40: Exit MemoryLeakExample_test2NoLeak \n " color=yellow style=filled]
39 [label="39: Start MemoryLeakExample_test2NoLeak\nFormals: \nLocals: allowedPublicKey:struct __SecKey * \n DECLARE_LOCALS(&return,&allowedPublicKey); [line 73]\n NULLIFY(&allowedPublicKey,false); [line 73]\n " color=yellow style=filled] 39 [label="39: Start MemoryLeakExample_test2NoLeak\nFormals: \nLocals: allowedPublicKey:struct __SecKey * \n DECLARE_LOCALS(&return,&allowedPublicKey); [line 70]\n NULLIFY(&allowedPublicKey,false); [line 70]\n " color=yellow style=filled]
39 -> 42 ; 39 -> 42 ;
38 [label="38: DeclStmt \n n$28=*&trust:struct __SecTrust * [line 70]\n n$29=_fun_SecTrustCopyPublicKey(n$28:struct __SecTrust *) [line 70]\n *&allowedPublicKey:struct __SecKey *=n$29 [line 70]\n REMOVE_TEMPS(n$28,n$29); [line 70]\n NULLIFY(&allowedPublicKey,false); [line 70]\n NULLIFY(&trust,false); [line 70]\n APPLY_ABSTRACTION; [line 70]\n " shape="box"] 38 [label="38: Call _fun_SecTrustCopyPublicKey \n n$28=*&trust:struct __SecTrust * [line 67]\n n$29=_fun_SecTrustCopyPublicKey(n$28:struct __SecTrust *) [line 67]\n REMOVE_TEMPS(n$28,n$29); [line 67]\n NULLIFY(&trust,false); [line 67]\n APPLY_ABSTRACTION; [line 67]\n " shape="box"]
38 -> 37 ; 38 -> 37 ;
37 [label="37: Exit MemoryLeakExample_test2: \n " color=yellow style=filled] 37 [label="37: Exit MemoryLeakExample_test2: \n " color=yellow style=filled]
36 [label="36: Start MemoryLeakExample_test2:\nFormals: trust:struct __SecTrust *\nLocals: allowedPublicKey:struct __SecKey * \n DECLARE_LOCALS(&return,&allowedPublicKey); [line 69]\n NULLIFY(&allowedPublicKey,false); [line 69]\n " color=yellow style=filled] 36 [label="36: Start MemoryLeakExample_test2:\nFormals: trust:struct __SecTrust *\nLocals: \n DECLARE_LOCALS(&return); [line 66]\n " color=yellow style=filled]
36 -> 38 ; 36 -> 38 ;
35 [label="35: DeclStmt \n n$26=*&rect:struct CGRect [line 62]\n n$27=_fun_CGRectGetHeight(n$26:struct CGRect ) [line 62]\n *&lineThickness:double =(0.200000 * n$27) [line 62]\n REMOVE_TEMPS(n$26,n$27); [line 62]\n NULLIFY(&rect,false); [line 62]\n NULLIFY(&lineThickness,false); [line 62]\n " shape="box"] 35 [label="35: DeclStmt \n n$26=*&rect:struct CGRect [line 59]\n n$27=_fun_CGRectGetHeight(n$26:struct CGRect ) [line 59]\n *&lineThickness:double =(0.200000 * n$27) [line 59]\n REMOVE_TEMPS(n$26,n$27); [line 59]\n NULLIFY(&rect,false); [line 59]\n NULLIFY(&lineThickness,false); [line 59]\n " shape="box"]
35 -> 34 ; 35 -> 34 ;
34 [label="34: DeclStmt \n n$25=_fun_CGPathCreateMutable() [line 65]\n *&path1:struct CGPath *=n$25 [line 65]\n REMOVE_TEMPS(n$25); [line 65]\n " shape="box"] 34 [label="34: DeclStmt \n n$25=_fun_CGPathCreateMutable() [line 62]\n *&path1:struct CGPath *=n$25 [line 62]\n REMOVE_TEMPS(n$25); [line 62]\n " shape="box"]
34 -> 33 ; 34 -> 33 ;
33 [label="33: Call _fun___objc_release_cf \n n$24=*&path1:struct CGPath * [line 66]\n _fun___objc_release_cf(1:_Bool ,n$24:void *) [line 66]\n REMOVE_TEMPS(n$24); [line 66]\n NULLIFY(&path1,false); [line 66]\n APPLY_ABSTRACTION; [line 66]\n " shape="box"] 33 [label="33: Call _fun___objc_release_cf \n n$24=*&path1:struct CGPath * [line 63]\n _fun___objc_release_cf(1:_Bool ,n$24:void *) [line 63]\n REMOVE_TEMPS(n$24); [line 63]\n NULLIFY(&path1,false); [line 63]\n APPLY_ABSTRACTION; [line 63]\n " shape="box"]
33 -> 32 ; 33 -> 32 ;
32 [label="32: Exit MemoryLeakExample_createCloseCrossGlyphNoLeak: \n " color=yellow style=filled] 32 [label="32: Exit MemoryLeakExample_createCloseCrossGlyphNoLeak: \n " color=yellow style=filled]
31 [label="31: Start MemoryLeakExample_createCloseCrossGlyphNoLeak:\nFormals: rect:struct CGRect \nLocals: path1:struct CGPath * lineThickness:double \n DECLARE_LOCALS(&return,&path1,&lineThickness); [line 61]\n NULLIFY(&lineThickness,false); [line 61]\n NULLIFY(&path1,false); [line 61]\n " color=yellow style=filled] 31 [label="31: Start MemoryLeakExample_createCloseCrossGlyphNoLeak:\nFormals: rect:struct CGRect \nLocals: path1:struct CGPath * lineThickness:double \n DECLARE_LOCALS(&return,&path1,&lineThickness); [line 58]\n NULLIFY(&lineThickness,false); [line 58]\n NULLIFY(&path1,false); [line 58]\n " color=yellow style=filled]
31 -> 35 ; 31 -> 35 ;
30 [label="30: DeclStmt \n n$22=*&rect:struct CGRect [line 55]\n n$23=_fun_CGRectGetHeight(n$22:struct CGRect ) [line 55]\n *&lineThickness:double =(0.200000 * n$23) [line 55]\n REMOVE_TEMPS(n$22,n$23); [line 55]\n NULLIFY(&rect,false); [line 55]\n NULLIFY(&lineThickness,false); [line 55]\n " shape="box"] 30 [label="30: BinaryOperatorStmt: Mul \n n$22=*&rect:struct CGRect [line 54]\n n$23=_fun_CGRectGetHeight(n$22:struct CGRect ) [line 54]\n REMOVE_TEMPS(n$22,n$23); [line 54]\n NULLIFY(&rect,false); [line 54]\n " shape="box"]
30 -> 29 ; 30 -> 29 ;
29 [label="29: DeclStmt \n n$21=_fun_CGPathCreateMutable() [line 58]\n *&path1:struct CGPath *=n$21 [line 58]\n REMOVE_TEMPS(n$21); [line 58]\n NULLIFY(&path1,false); [line 58]\n APPLY_ABSTRACTION; [line 58]\n " shape="box"] 29 [label="29: Call _fun_CGPathCreateMutable \n n$21=_fun_CGPathCreateMutable() [line 55]\n REMOVE_TEMPS(n$21); [line 55]\n APPLY_ABSTRACTION; [line 55]\n " shape="box"]
29 -> 28 ; 29 -> 28 ;
28 [label="28: Exit MemoryLeakExample_createCloseCrossGlyph: \n " color=yellow style=filled] 28 [label="28: Exit MemoryLeakExample_createCloseCrossGlyph: \n " color=yellow style=filled]
27 [label="27: Start MemoryLeakExample_createCloseCrossGlyph:\nFormals: rect:struct CGRect \nLocals: path1:struct CGPath * lineThickness:double \n DECLARE_LOCALS(&return,&path1,&lineThickness); [line 54]\n NULLIFY(&lineThickness,false); [line 54]\n NULLIFY(&path1,false); [line 54]\n " color=yellow style=filled] 27 [label="27: Start MemoryLeakExample_createCloseCrossGlyph:\nFormals: rect:struct CGRect \nLocals: \n DECLARE_LOCALS(&return); [line 53]\n " color=yellow style=filled]
27 -> 30 ; 27 -> 30 ;
26 [label="26: DeclStmt \n n$20=_fun_CTFramesetterCreateWithAttributedString(0:struct __CFAttributedString *) [line 50]\n *&framesetter:struct __CTFramesetter *=n$20 [line 50]\n REMOVE_TEMPS(n$20); [line 50]\n " shape="box"] 26 [label="26: DeclStmt \n n$20=_fun_CTFramesetterCreateWithAttributedString(0:struct __CFAttributedString *) [line 49]\n *&framesetter:struct __CTFramesetter *=n$20 [line 49]\n REMOVE_TEMPS(n$20); [line 49]\n " shape="box"]
26 -> 25 ; 26 -> 25 ;
25 [label="25: Call _fun___objc_release_cf \n n$19=*&framesetter:struct __CTFramesetter * [line 51]\n _fun___objc_release_cf(1:_Bool ,n$19:void *) [line 51]\n REMOVE_TEMPS(n$19); [line 51]\n NULLIFY(&framesetter,false); [line 51]\n APPLY_ABSTRACTION; [line 51]\n " shape="box"] 25 [label="25: Call _fun___objc_release_cf \n n$19=*&framesetter:struct __CTFramesetter * [line 50]\n _fun___objc_release_cf(1:_Bool ,n$19:void *) [line 50]\n REMOVE_TEMPS(n$19); [line 50]\n NULLIFY(&framesetter,false); [line 50]\n APPLY_ABSTRACTION; [line 50]\n " shape="box"]
25 -> 24 ; 25 -> 24 ;
24 [label="24: Exit MemoryLeakExample_test1NoLeak \n " color=yellow style=filled] 24 [label="24: Exit MemoryLeakExample_test1NoLeak \n " color=yellow style=filled]
23 [label="23: Start MemoryLeakExample_test1NoLeak\nFormals: \nLocals: framesetter:struct __CTFramesetter * \n DECLARE_LOCALS(&return,&framesetter); [line 49]\n NULLIFY(&framesetter,false); [line 49]\n " color=yellow style=filled] 23 [label="23: Start MemoryLeakExample_test1NoLeak\nFormals: \nLocals: framesetter:struct __CTFramesetter * \n DECLARE_LOCALS(&return,&framesetter); [line 48]\n NULLIFY(&framesetter,false); [line 48]\n " color=yellow style=filled]
23 -> 26 ; 23 -> 26 ;
22 [label="22: DeclStmt \n n$17=*&str:struct __CFAttributedString * [line 46]\n n$18=_fun_CTFramesetterCreateWithAttributedString(n$17:struct __CFAttributedString *) [line 46]\n *&framesetter:struct __CTFramesetter *=n$18 [line 46]\n REMOVE_TEMPS(n$17,n$18); [line 46]\n NULLIFY(&framesetter,false); [line 46]\n NULLIFY(&str,false); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] 22 [label="22: Call _fun_CTFramesetterCreateWithAttributedString \n n$17=*&str:struct __CFAttributedString * [line 45]\n n$18=_fun_CTFramesetterCreateWithAttributedString(n$17:struct __CFAttributedString *) [line 45]\n REMOVE_TEMPS(n$17,n$18); [line 45]\n NULLIFY(&str,false); [line 45]\n APPLY_ABSTRACTION; [line 45]\n " shape="box"]
22 -> 21 ; 22 -> 21 ;
21 [label="21: Exit MemoryLeakExample_test1: \n " color=yellow style=filled] 21 [label="21: Exit MemoryLeakExample_test1: \n " color=yellow style=filled]
20 [label="20: Start MemoryLeakExample_test1:\nFormals: str:struct __CFAttributedString *\nLocals: framesetter:struct __CTFramesetter * \n DECLARE_LOCALS(&return,&framesetter); [line 45]\n NULLIFY(&framesetter,false); [line 45]\n " color=yellow style=filled] 20 [label="20: Start MemoryLeakExample_test1:\nFormals: str:struct __CFAttributedString *\nLocals: \n DECLARE_LOCALS(&return); [line 44]\n " color=yellow style=filled]
20 -> 22 ; 20 -> 22 ;
19 [label="19: DeclStmt \n n$16=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 41]\n *&maString:struct __CFAttributedString *=n$16 [line 41]\n REMOVE_TEMPS(n$16); [line 41]\n " shape="box"] 19 [label="19: DeclStmt \n n$16=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 40]\n *&maString:struct __CFAttributedString *=n$16 [line 40]\n REMOVE_TEMPS(n$16); [line 40]\n " shape="box"]
19 -> 18 ; 19 -> 18 ;
18 [label="18: Call _fun___objc_release_cf \n n$15=*&maString:struct __CFAttributedString * [line 42]\n _fun___objc_release_cf(1:_Bool ,n$15:void *) [line 42]\n REMOVE_TEMPS(n$15); [line 42]\n NULLIFY(&maString,false); [line 42]\n APPLY_ABSTRACTION; [line 42]\n " shape="box"] 18 [label="18: Call _fun___objc_release_cf \n n$15=*&maString:struct __CFAttributedString * [line 41]\n _fun___objc_release_cf(1:_Bool ,n$15:void *) [line 41]\n REMOVE_TEMPS(n$15); [line 41]\n NULLIFY(&maString,false); [line 41]\n APPLY_ABSTRACTION; [line 41]\n " shape="box"]
18 -> 17 ; 18 -> 17 ;
17 [label="17: Exit MemoryLeakExample_measureFrameSizeForTextNoLeak \n " color=yellow style=filled] 17 [label="17: Exit MemoryLeakExample_measureFrameSizeForTextNoLeak \n " color=yellow style=filled]
16 [label="16: Start MemoryLeakExample_measureFrameSizeForTextNoLeak\nFormals: \nLocals: maString:struct __CFAttributedString * \n DECLARE_LOCALS(&return,&maString); [line 39]\n NULLIFY(&maString,false); [line 39]\n " color=yellow style=filled] 16 [label="16: Start MemoryLeakExample_measureFrameSizeForTextNoLeak\nFormals: \nLocals: maString:struct __CFAttributedString * \n DECLARE_LOCALS(&return,&maString); [line 38]\n NULLIFY(&maString,false); [line 38]\n " color=yellow style=filled]
16 -> 19 ; 16 -> 19 ;
15 [label="15: DeclStmt \n n$14=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 36]\n *&maString:struct __CFAttributedString *=n$14 [line 36]\n REMOVE_TEMPS(n$14); [line 36]\n NULLIFY(&maString,false); [line 36]\n APPLY_ABSTRACTION; [line 36]\n " shape="box"] 15 [label="15: Call _fun_CFAttributedStringCreateMutable \n n$14=_fun_CFAttributedStringCreateMutable(0:struct __CFAllocator *,0:long ) [line 35]\n REMOVE_TEMPS(n$14); [line 35]\n APPLY_ABSTRACTION; [line 35]\n " shape="box"]
15 -> 14 ; 15 -> 14 ;
14 [label="14: Exit MemoryLeakExample_measureFrameSizeForText \n " color=yellow style=filled] 14 [label="14: Exit MemoryLeakExample_measureFrameSizeForText \n " color=yellow style=filled]
13 [label="13: Start MemoryLeakExample_measureFrameSizeForText\nFormals: \nLocals: maString:struct __CFAttributedString * \n DECLARE_LOCALS(&return,&maString); [line 34]\n NULLIFY(&maString,false); [line 34]\n " color=yellow style=filled] 13 [label="13: Start MemoryLeakExample_measureFrameSizeForText\nFormals: \nLocals: \n DECLARE_LOCALS(&return); [line 34]\n " color=yellow style=filled]
13 -> 15 ; 13 -> 15 ;

@ -32,8 +32,7 @@
} }
+ (void)measureFrameSizeForText { + (void)measureFrameSizeForText {
CFMutableAttributedStringRef maString = CFAttributedStringCreateMutable(nil, 0);
CFAttributedStringCreateMutable(nil, 0);
} }
+ (void)measureFrameSizeForTextNoLeak { + (void)measureFrameSizeForTextNoLeak {
@ -43,7 +42,7 @@
} }
+ (void)test1:(CFAttributedStringRef)str { + (void)test1:(CFAttributedStringRef)str {
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(str); CTFramesetterCreateWithAttributedString(str);
} }
+ (void)test1NoLeak { + (void)test1NoLeak {
@ -52,10 +51,8 @@
} }
+ (void)createCloseCrossGlyph:(CGRect)rect { + (void)createCloseCrossGlyph:(CGRect)rect {
CGFloat lineThickness = 0.20f * CGRectGetHeight(rect); 0.20f * CGRectGetHeight(rect);
CGPathCreateMutable();
// One rectangle
CGMutablePathRef path1 = CGPathCreateMutable();
} }
+ (void)createCloseCrossGlyphNoLeak:(CGRect)rect { + (void)createCloseCrossGlyphNoLeak:(CGRect)rect {
@ -67,7 +64,7 @@
} }
+ (void)test2:(SecTrustRef)trust { + (void)test2:(SecTrustRef)trust {
SecKeyRef allowedPublicKey = SecTrustCopyPublicKey(trust); SecTrustCopyPublicKey(trust);
} }
+ (void)test2NoLeak { + (void)test2NoLeak {
@ -87,4 +84,30 @@ CGColorRef FBColorCreateWithGray(CGFloat gray, CGFloat a);
CGColorRelease(borderColor); CGColorRelease(borderColor);
} }
- (int)regularLeak {
int* x = malloc(sizeof(int));
*x = 7;
return *x;
}
- (int)blockCapturedVarLeak {
int* x = malloc(sizeof(int));
*x = 2;
int (^blk)(void) = ^() {
return *x;
};
return blk();
}
- (int)blockFreeNoLeakTODO {
int* x = malloc(sizeof(int));
*x = 2;
int (^blk)(void) = ^() {
int i = *x;
free(x);
return i;
};
return blk();
}
@end @end

@ -7,11 +7,11 @@ digraph iCFG {
54 -> 53 ; 54 -> 53 ;
53 [label="53: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_capturedNoNullDeref______5); [line 59]\n n$37=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_capturedNoNullDeref______5 ):unsigned long ) [line 59]\n *&__objc_anonymous_block_BlockVar_capturedNoNullDeref______5:class __objc_anonymous_block_BlockVar_capturedNoNullDeref______5 =n$37 [line 59]\n n$38=*&x:int * [line 59]\n *n$37.x:int *=n$38 [line 59]\n n$34=*&x:int * [line 59]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_capturedNoNullDeref______5,n$34) [line 59]\n REMOVE_TEMPS(n$37,n$38,n$34); [line 59]\n " shape="box"] 53 [label="53: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_capturedNoNullDeref______5); [line 59]\n n$37=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_capturedNoNullDeref______5 ):unsigned long ) [line 59]\n *&__objc_anonymous_block_BlockVar_capturedNoNullDeref______5:class __objc_anonymous_block_BlockVar_capturedNoNullDeref______5 =n$37 [line 59]\n n$38=*&x:int * [line 59]\n *n$37.x:int *=n$38 [line 59]\n n$34=*&x:int * [line 59]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_capturedNoNullDeref______5,n$34) [line 59]\n REMOVE_TEMPS(n$37,n$38,n$34); [line 59]\n NULLIFY(&x,false); [line 59]\n " shape="box"]
53 -> 49 ; 53 -> 49 ;
52 [label="52: Return Stmt \n n$35=*&x:int * [line 60]\n n$36=*n$35:int [line 60]\n *&return:int =n$36 [line 60]\n REMOVE_TEMPS(n$35,n$36); [line 60]\n APPLY_ABSTRACTION; [line 60]\n " shape="box"] 52 [label="52: Return Stmt \n n$35=*&x:int * [line 60]\n n$36=*n$35:int [line 60]\n *&return:int =n$36 [line 60]\n REMOVE_TEMPS(n$35,n$36); [line 60]\n NULLIFY(&x,false); [line 60]\n APPLY_ABSTRACTION; [line 60]\n " shape="box"]
52 -> 51 ; 52 -> 51 ;
@ -22,7 +22,7 @@ digraph iCFG {
50 -> 52 ; 50 -> 52 ;
49 [label="49: BinaryOperatorStmt: Assign \n *&x:int *=0 [line 62]\n " shape="box"] 49 [label="49: BinaryOperatorStmt: Assign \n *&x:int *=0 [line 62]\n NULLIFY(&x,false); [line 62]\n " shape="box"]
49 -> 48 ; 49 -> 48 ;
@ -33,7 +33,7 @@ digraph iCFG {
47 [label="47: Exit BlockVar_capturedNoNullDeref \n " color=yellow style=filled] 47 [label="47: Exit BlockVar_capturedNoNullDeref \n " color=yellow style=filled]
46 [label="46: Start BlockVar_capturedNoNullDeref\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * i:int \n DECLARE_LOCALS(&return,&my_block,&x,&i); [line 56]\n NULLIFY(&my_block,false); [line 56]\n NULLIFY(&self,false); [line 56]\n " color=yellow style=filled] 46 [label="46: Start BlockVar_capturedNoNullDeref\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * i:int \n DECLARE_LOCALS(&return,&my_block,&x,&i); [line 56]\n NULLIFY(&my_block,false); [line 56]\n NULLIFY(&self,false); [line 56]\n NULLIFY(&x,false); [line 56]\n " color=yellow style=filled]
46 -> 55 ; 46 -> 55 ;
@ -41,11 +41,11 @@ digraph iCFG {
45 -> 44 ; 45 -> 44 ;
44 [label="44: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_capturedNullDeref______4); [line 50]\n n$30=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_capturedNullDeref______4 ):unsigned long ) [line 50]\n *&__objc_anonymous_block_BlockVar_capturedNullDeref______4:class __objc_anonymous_block_BlockVar_capturedNullDeref______4 =n$30 [line 50]\n n$31=*&x:int * [line 50]\n *n$30.x:int *=n$31 [line 50]\n n$27=*&x:int * [line 50]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_capturedNullDeref______4,n$27) [line 50]\n REMOVE_TEMPS(n$30,n$31,n$27); [line 50]\n " shape="box"] 44 [label="44: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_capturedNullDeref______4); [line 50]\n n$30=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_capturedNullDeref______4 ):unsigned long ) [line 50]\n *&__objc_anonymous_block_BlockVar_capturedNullDeref______4:class __objc_anonymous_block_BlockVar_capturedNullDeref______4 =n$30 [line 50]\n n$31=*&x:int * [line 50]\n *n$30.x:int *=n$31 [line 50]\n n$27=*&x:int * [line 50]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_capturedNullDeref______4,n$27) [line 50]\n REMOVE_TEMPS(n$30,n$31,n$27); [line 50]\n NULLIFY(&x,false); [line 50]\n " shape="box"]
44 -> 40 ; 44 -> 40 ;
43 [label="43: Return Stmt \n n$28=*&x:int * [line 51]\n n$29=*n$28:int [line 51]\n *&return:int =n$29 [line 51]\n REMOVE_TEMPS(n$28,n$29); [line 51]\n APPLY_ABSTRACTION; [line 51]\n " shape="box"] 43 [label="43: Return Stmt \n n$28=*&x:int * [line 51]\n n$29=*n$28:int [line 51]\n *&return:int =n$29 [line 51]\n REMOVE_TEMPS(n$28,n$29); [line 51]\n NULLIFY(&x,false); [line 51]\n APPLY_ABSTRACTION; [line 51]\n " shape="box"]
43 -> 42 ; 43 -> 42 ;
@ -63,7 +63,7 @@ digraph iCFG {
39 [label="39: Exit BlockVar_capturedNullDeref \n " color=yellow style=filled] 39 [label="39: Exit BlockVar_capturedNullDeref \n " color=yellow style=filled]
38 [label="38: Start BlockVar_capturedNullDeref\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * \n DECLARE_LOCALS(&return,&my_block,&x); [line 48]\n NULLIFY(&my_block,false); [line 48]\n NULLIFY(&self,false); [line 48]\n " color=yellow style=filled] 38 [label="38: Start BlockVar_capturedNullDeref\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * \n DECLARE_LOCALS(&return,&my_block,&x); [line 48]\n NULLIFY(&my_block,false); [line 48]\n NULLIFY(&self,false); [line 48]\n NULLIFY(&x,false); [line 48]\n " color=yellow style=filled]
38 -> 45 ; 38 -> 45 ;
@ -75,11 +75,11 @@ digraph iCFG {
36 -> 35 ; 36 -> 35 ;
35 [label="35: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_blockPostOk______3); [line 42]\n n$23=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_blockPostOk______3 ):unsigned long ) [line 42]\n *&__objc_anonymous_block_BlockVar_blockPostOk______3:class __objc_anonymous_block_BlockVar_blockPostOk______3 =n$23 [line 42]\n n$24=*&x:int * [line 42]\n *n$23.x:int *=n$24 [line 42]\n n$21=*&x:int * [line 42]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_blockPostOk______3,n$21) [line 42]\n REMOVE_TEMPS(n$23,n$24,n$21); [line 42]\n " shape="box"] 35 [label="35: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_blockPostOk______3); [line 42]\n n$23=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_blockPostOk______3 ):unsigned long ) [line 42]\n *&__objc_anonymous_block_BlockVar_blockPostOk______3:class __objc_anonymous_block_BlockVar_blockPostOk______3 =n$23 [line 42]\n n$24=*&x:int * [line 42]\n *n$23.x:int *=n$24 [line 42]\n n$21=*&x:int * [line 42]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_blockPostOk______3,n$21) [line 42]\n REMOVE_TEMPS(n$23,n$24,n$21); [line 42]\n NULLIFY(&x,false); [line 42]\n " shape="box"]
35 -> 31 ; 35 -> 31 ;
34 [label="34: Return Stmt \n n$22=*&x:int * [line 43]\n *&return:int *=n$22 [line 43]\n REMOVE_TEMPS(n$22); [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"] 34 [label="34: Return Stmt \n n$22=*&x:int * [line 43]\n *&return:int *=n$22 [line 43]\n REMOVE_TEMPS(n$22); [line 43]\n NULLIFY(&x,false); [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"]
34 -> 33 ; 34 -> 33 ;
@ -97,7 +97,7 @@ digraph iCFG {
30 [label="30: Exit BlockVar_blockPostOk \n " color=yellow style=filled] 30 [label="30: Exit BlockVar_blockPostOk \n " color=yellow style=filled]
29 [label="29: Start BlockVar_blockPostOk\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * i:int \n DECLARE_LOCALS(&return,&my_block,&x,&i); [line 39]\n NULLIFY(&my_block,false); [line 39]\n NULLIFY(&self,false); [line 39]\n " color=yellow style=filled] 29 [label="29: Start BlockVar_blockPostOk\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * i:int \n DECLARE_LOCALS(&return,&my_block,&x,&i); [line 39]\n NULLIFY(&my_block,false); [line 39]\n NULLIFY(&self,false); [line 39]\n NULLIFY(&x,false); [line 39]\n " color=yellow style=filled]
29 -> 37 ; 29 -> 37 ;
@ -105,11 +105,11 @@ digraph iCFG {
28 -> 27 ; 28 -> 27 ;
27 [label="27: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_blockPostBad______2); [line 33]\n n$16=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_blockPostBad______2 ):unsigned long ) [line 33]\n *&__objc_anonymous_block_BlockVar_blockPostBad______2:class __objc_anonymous_block_BlockVar_blockPostBad______2 =n$16 [line 33]\n n$17=*&x:int * [line 33]\n *n$16.x:int *=n$17 [line 33]\n n$14=*&x:int * [line 33]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_blockPostBad______2,n$14) [line 33]\n REMOVE_TEMPS(n$16,n$17,n$14); [line 33]\n " shape="box"] 27 [label="27: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_BlockVar_blockPostBad______2); [line 33]\n n$16=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_BlockVar_blockPostBad______2 ):unsigned long ) [line 33]\n *&__objc_anonymous_block_BlockVar_blockPostBad______2:class __objc_anonymous_block_BlockVar_blockPostBad______2 =n$16 [line 33]\n n$17=*&x:int * [line 33]\n *n$16.x:int *=n$17 [line 33]\n n$14=*&x:int * [line 33]\n *&my_block:_fn_ (*)=(_fun___objc_anonymous_block_BlockVar_blockPostBad______2,n$14) [line 33]\n REMOVE_TEMPS(n$16,n$17,n$14); [line 33]\n NULLIFY(&x,false); [line 33]\n " shape="box"]
27 -> 23 ; 27 -> 23 ;
26 [label="26: Return Stmt \n n$15=*&x:int * [line 34]\n *&return:int *=n$15 [line 34]\n REMOVE_TEMPS(n$15); [line 34]\n APPLY_ABSTRACTION; [line 34]\n " shape="box"] 26 [label="26: Return Stmt \n n$15=*&x:int * [line 34]\n *&return:int *=n$15 [line 34]\n REMOVE_TEMPS(n$15); [line 34]\n NULLIFY(&x,false); [line 34]\n APPLY_ABSTRACTION; [line 34]\n " shape="box"]
26 -> 25 ; 26 -> 25 ;
@ -127,7 +127,7 @@ digraph iCFG {
22 [label="22: Exit BlockVar_blockPostBad \n " color=yellow style=filled] 22 [label="22: Exit BlockVar_blockPostBad \n " color=yellow style=filled]
21 [label="21: Start BlockVar_blockPostBad\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * \n DECLARE_LOCALS(&return,&my_block,&x); [line 31]\n NULLIFY(&my_block,false); [line 31]\n NULLIFY(&self,false); [line 31]\n " color=yellow style=filled] 21 [label="21: Start BlockVar_blockPostBad\nFormals: self:class BlockVar *\nLocals: my_block:_fn_ (*) x:int * \n DECLARE_LOCALS(&return,&my_block,&x); [line 31]\n NULLIFY(&my_block,false); [line 31]\n NULLIFY(&self,false); [line 31]\n NULLIFY(&x,false); [line 31]\n " color=yellow style=filled]
21 -> 28 ; 21 -> 28 ;

@ -18,7 +18,7 @@ digraph iCFG {
21 -> 20 ; 21 -> 20 ;
20 [label="20: BinaryOperatorStmt: Assign \n DECLARE_LOCALS(&__objc_anonymous_block_main1______2); [line 18]\n n$27=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_main1______2 ):unsigned long ) [line 18]\n *&__objc_anonymous_block_main1______2:class __objc_anonymous_block_main1______2 =n$27 [line 18]\n n$28=*&x:int [line 18]\n *n$27.x:int =n$28 [line 18]\n n$11=*&x:int [line 18]\n *&addblock:_fn_ (*)=(_fun___objc_anonymous_block_main1______2,n$11) [line 18]\n REMOVE_TEMPS(n$27,n$28,n$11); [line 18]\n " shape="box"] 20 [label="20: BinaryOperatorStmt: Assign \n DECLARE_LOCALS(&__objc_anonymous_block_main1______2); [line 18]\n n$27=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_main1______2 ):unsigned long ) [line 18]\n *&__objc_anonymous_block_main1______2:class __objc_anonymous_block_main1______2 =n$27 [line 18]\n n$28=*&x:int [line 18]\n *n$27.x:int =n$28 [line 18]\n n$11=*&x:int [line 18]\n *&addblock:_fn_ (*)=(_fun___objc_anonymous_block_main1______2,n$11) [line 18]\n REMOVE_TEMPS(n$27,n$28,n$11); [line 18]\n NULLIFY(&x,false); [line 18]\n " shape="box"]
20 -> 10 ; 20 -> 10 ;
@ -26,11 +26,11 @@ digraph iCFG {
19 -> 18 ; 19 -> 18 ;
18 [label="18: BinaryOperatorStmt: Assign \n DECLARE_LOCALS(&__objc_anonymous_block___objc_anonymous_block_main1______2______3); [line 24]\n n$23=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block___objc_anonymous_block_main1______2______3 ):unsigned long ) [line 24]\n *&__objc_anonymous_block___objc_anonymous_block_main1______2______3:class __objc_anonymous_block___objc_anonymous_block_main1______2______3 =n$23 [line 24]\n n$24=*&x:int [line 24]\n n$25=*&bla:int [line 24]\n n$26=*&#GB$main1_s:int [line 24]\n *n$23.x:int =n$24 [line 24]\n *n$23.bla:int =n$25 [line 24]\n *n$23.main1_s:int =n$26 [line 24]\n n$17=*&x:int [line 24]\n n$18=*&bla:int [line 24]\n *&addblock2:_fn_ (*)=(_fun___objc_anonymous_block___objc_anonymous_block_main1______2______3,n$17,n$18) [line 24]\n REMOVE_TEMPS(n$23,n$24,n$25,n$26,n$17,n$18); [line 24]\n " shape="box"] 18 [label="18: BinaryOperatorStmt: Assign \n DECLARE_LOCALS(&__objc_anonymous_block___objc_anonymous_block_main1______2______3); [line 24]\n n$23=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block___objc_anonymous_block_main1______2______3 ):unsigned long ) [line 24]\n *&__objc_anonymous_block___objc_anonymous_block_main1______2______3:class __objc_anonymous_block___objc_anonymous_block_main1______2______3 =n$23 [line 24]\n n$24=*&x:int [line 24]\n n$25=*&bla:int [line 24]\n n$26=*&#GB$main1_s:int [line 24]\n *n$23.x:int =n$24 [line 24]\n *n$23.bla:int =n$25 [line 24]\n *n$23.main1_s:int =n$26 [line 24]\n n$17=*&x:int [line 24]\n n$18=*&bla:int [line 24]\n *&addblock2:_fn_ (*)=(_fun___objc_anonymous_block___objc_anonymous_block_main1______2______3,n$17,n$18) [line 24]\n REMOVE_TEMPS(n$23,n$24,n$25,n$26,n$17,n$18); [line 24]\n NULLIFY(&x,false); [line 24]\n " shape="box"]
18 -> 14 ; 18 -> 14 ;
17 [label="17: Return Stmt \n n$19=*&z:int [line 25]\n n$20=*&#GB$main1_s:int [line 25]\n n$21=*&x:int [line 25]\n n$22=*&bla:int [line 25]\n *&return:int =(((n$19 + n$20) + n$21) + n$22) [line 25]\n REMOVE_TEMPS(n$19,n$20,n$21,n$22); [line 25]\n NULLIFY(&z,false); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"] 17 [label="17: Return Stmt \n n$19=*&z:int [line 25]\n n$20=*&#GB$main1_s:int [line 25]\n n$21=*&x:int [line 25]\n n$22=*&bla:int [line 25]\n *&return:int =(((n$19 + n$20) + n$21) + n$22) [line 25]\n REMOVE_TEMPS(n$19,n$20,n$21,n$22); [line 25]\n NULLIFY(&bla,false); [line 25]\n NULLIFY(&x,false); [line 25]\n NULLIFY(&z,false); [line 25]\n APPLY_ABSTRACTION; [line 25]\n " shape="box"]
17 -> 16 ; 17 -> 16 ;
@ -45,14 +45,14 @@ digraph iCFG {
14 -> 13 ; 14 -> 13 ;
13 [label="13: Return Stmt \n n$12=*&c:int [line 29]\n n$13=*&add2:int [line 29]\n n$14=*&bla:int [line 29]\n *&return:int =((n$12 + n$13) + n$14) [line 29]\n REMOVE_TEMPS(n$12,n$13,n$14); [line 29]\n NULLIFY(&__objc_anonymous_block___objc_anonymous_block_main1______2______3,true); [line 29]\n NULLIFY(&add2,false); [line 29]\n NULLIFY(&c,false); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] 13 [label="13: Return Stmt \n n$12=*&c:int [line 29]\n n$13=*&add2:int [line 29]\n n$14=*&bla:int [line 29]\n *&return:int =((n$12 + n$13) + n$14) [line 29]\n REMOVE_TEMPS(n$12,n$13,n$14); [line 29]\n NULLIFY(&__objc_anonymous_block___objc_anonymous_block_main1______2______3,true); [line 29]\n NULLIFY(&add2,false); [line 29]\n NULLIFY(&bla,false); [line 29]\n NULLIFY(&c,false); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"]
13 -> 12 ; 13 -> 12 ;
12 [label="12: Exit __objc_anonymous_block_main1______2 \n " color=yellow style=filled] 12 [label="12: Exit __objc_anonymous_block_main1______2 \n " color=yellow style=filled]
11 [label="11: Start __objc_anonymous_block_main1______2\nFormals: x:int c:int d:int \nLocals: bla:int add2:int addblock2:_fn_ (*)\nCaptured: x:int \n DECLARE_LOCALS(&return,&bla,&add2,&addblock2); [line 18]\n NULLIFY(&add2,false); [line 18]\n NULLIFY(&addblock2,false); [line 18]\n NULLIFY(&d,false); [line 18]\n " color=yellow style=filled] 11 [label="11: Start __objc_anonymous_block_main1______2\nFormals: x:int c:int d:int \nLocals: bla:int add2:int addblock2:_fn_ (*)\nCaptured: x:int \n DECLARE_LOCALS(&return,&bla,&add2,&addblock2); [line 18]\n NULLIFY(&add2,false); [line 18]\n NULLIFY(&addblock2,false); [line 18]\n NULLIFY(&bla,false); [line 18]\n NULLIFY(&d,false); [line 18]\n " color=yellow style=filled]
11 -> 19 ; 11 -> 19 ;
@ -90,7 +90,7 @@ digraph iCFG {
2 [label="2: Exit main1 \n " color=yellow style=filled] 2 [label="2: Exit main1 \n " color=yellow style=filled]
1 [label="1: Start main1\nFormals: y:int \nLocals: addblock:_fn_ (*) add2:int add1:int x:int \n DECLARE_LOCALS(&return,&addblock,&add2,&add1,&x); [line 10]\n NULLIFY(&add1,false); [line 10]\n NULLIFY(&add2,false); [line 10]\n NULLIFY(&addblock,false); [line 10]\n NULLIFY(&y,false); [line 10]\n " color=yellow style=filled] 1 [label="1: Start main1\nFormals: y:int \nLocals: addblock:_fn_ (*) add2:int add1:int x:int \n DECLARE_LOCALS(&return,&addblock,&add2,&add1,&x); [line 10]\n NULLIFY(&add1,false); [line 10]\n NULLIFY(&add2,false); [line 10]\n NULLIFY(&addblock,false); [line 10]\n NULLIFY(&x,false); [line 10]\n NULLIFY(&y,false); [line 10]\n " color=yellow style=filled]
1 -> 22 ; 1 -> 22 ;

@ -11,7 +11,7 @@ digraph iCFG {
16 -> 12 ; 16 -> 12 ;
15 [label="15: BinaryOperatorStmt: Assign \n n$6=*&z:int [line 26]\n *&#GB$g:int =(n$6 + 3) [line 26]\n REMOVE_TEMPS(n$6); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"] 15 [label="15: BinaryOperatorStmt: Assign \n n$6=*&z:int [line 26]\n *&#GB$g:int =(n$6 + 3) [line 26]\n REMOVE_TEMPS(n$6); [line 26]\n NULLIFY(&z,false); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"]
15 -> 14 ; 15 -> 14 ;
@ -30,11 +30,11 @@ digraph iCFG {
11 -> 6 ; 11 -> 6 ;
10 [label="10: Return Stmt \n NULLIFY(&p,false); [line 33]\n n$3=*&z:int [line 33]\n *&return:int =n$3 [line 33]\n REMOVE_TEMPS(n$3); [line 33]\n NULLIFY(&__objc_anonymous_block_My_manager_m______1,true); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"] 10 [label="10: Return Stmt \n NULLIFY(&p,false); [line 33]\n n$3=*&z:int [line 33]\n *&return:int =n$3 [line 33]\n REMOVE_TEMPS(n$3); [line 33]\n NULLIFY(&__objc_anonymous_block_My_manager_m______1,true); [line 33]\n NULLIFY(&z,false); [line 33]\n APPLY_ABSTRACTION; [line 33]\n " shape="box"]
10 -> 4 ; 10 -> 4 ;
9 [label="9: Return Stmt \n n$1=*&p:int * [line 31]\n n$2=*n$1:int [line 31]\n *&return:int =n$2 [line 31]\n REMOVE_TEMPS(n$1,n$2); [line 31]\n NULLIFY(&__objc_anonymous_block_My_manager_m______1,true); [line 31]\n NULLIFY(&p,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] 9 [label="9: Return Stmt \n NULLIFY(&z,false); [line 31]\n n$1=*&p:int * [line 31]\n n$2=*n$1:int [line 31]\n *&return:int =n$2 [line 31]\n REMOVE_TEMPS(n$1,n$2); [line 31]\n NULLIFY(&__objc_anonymous_block_My_manager_m______1,true); [line 31]\n NULLIFY(&p,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"]
9 -> 4 ; 9 -> 4 ;
@ -51,14 +51,14 @@ digraph iCFG {
6 -> 7 ; 6 -> 7 ;
6 -> 8 ; 6 -> 8 ;
5 [label="5: + \n NULLIFY(&__objc_anonymous_block_My_manager_m______1,true); [line 30]\n NULLIFY(&b,false); [line 30]\n NULLIFY(&p,false); [line 30]\n NULLIFY(&self,false); [line 30]\n " ] 5 [label="5: + \n NULLIFY(&__objc_anonymous_block_My_manager_m______1,true); [line 30]\n NULLIFY(&b,false); [line 30]\n NULLIFY(&p,false); [line 30]\n NULLIFY(&self,false); [line 30]\n NULLIFY(&z,false); [line 30]\n " ]
5 -> 4 ; 5 -> 4 ;
4 [label="4: Exit My_manager_m \n " color=yellow style=filled] 4 [label="4: Exit My_manager_m \n " color=yellow style=filled]
3 [label="3: Start My_manager_m\nFormals: self:class My_manager *\nLocals: p:int * z:int b:_fn_ (*) \n DECLARE_LOCALS(&return,&p,&z,&b); [line 21]\n NULLIFY(&b,false); [line 21]\n NULLIFY(&p,false); [line 21]\n NULLIFY(&self,false); [line 21]\n " color=yellow style=filled] 3 [label="3: Start My_manager_m\nFormals: self:class My_manager *\nLocals: p:int * z:int b:_fn_ (*) \n DECLARE_LOCALS(&return,&p,&z,&b); [line 21]\n NULLIFY(&b,false); [line 21]\n NULLIFY(&p,false); [line 21]\n NULLIFY(&self,false); [line 21]\n NULLIFY(&z,false); [line 21]\n " color=yellow style=filled]
3 -> 18 ; 3 -> 18 ;

@ -11,13 +11,13 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
@interface My_manager : NSObject @interface My_manager : NSObject
- (int)my_mehtod; - (int)my_method;
@end @end
@implementation My_manager @implementation My_manager
- (int)m { - (int)blockReleaseTODO {
void (^b)(int a); void (^b)(int a);
int z = 3; int z = 3;
CGContextRef context = CGBitmapContextCreate(NULL, 0, 0, 8, 0, 0, 0); CGContextRef context = CGBitmapContextCreate(NULL, 0, 0, 8, 0, 0, 0);
@ -26,7 +26,7 @@
if (newImage) if (newImage)
CGImageRelease(newImage); CGImageRelease(newImage);
}; };
b(z); b(z); // currently doesn't work due to PRECONDITION_NOT_MET here
if (context) if (context)
CGContextRelease(context); CGContextRelease(context);
return z; return z;

@ -41,7 +41,7 @@ digraph iCFG {
13 -> 9 ; 13 -> 9 ;
12 [label="12: BinaryOperatorStmt: Assign \n n$3=*&self:class A * [line 48]\n n$4=*&d:class D * [line 48]\n *n$3._data:class D *=n$4 [line 48]\n REMOVE_TEMPS(n$3,n$4); [line 48]\n NULLIFY(&d,false); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"] 12 [label="12: BinaryOperatorStmt: Assign \n n$3=*&self:class A * [line 48]\n n$4=*&d:class D * [line 48]\n *n$3._data:class D *=n$4 [line 48]\n REMOVE_TEMPS(n$3,n$4); [line 48]\n NULLIFY(&d,false); [line 48]\n NULLIFY(&self,false); [line 48]\n APPLY_ABSTRACTION; [line 48]\n " shape="box"]
12 -> 11 ; 12 -> 11 ;

@ -45,7 +45,9 @@ public class BlockReleaseTest {
public void whenInferRunsOnMnThenMemoryLeakIsNotFound() public void whenInferRunsOnMnThenMemoryLeakIsNotFound()
throws InterruptedException, IOException, InferException { throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd); InferResults inferResults = InferRunner.runInferObjC(inferCmd);
String[] procedures = { // no memory leak found String[] procedures = {
// TODO: don't report on this test
"blockReleaseTODO"
}; };
assertThat( assertThat(
"Results should contain the expected memory leak", "Results should contain the expected memory leak",

@ -10,8 +10,7 @@
package endtoend.objc; package endtoend.objc;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsErrorInMethod.contains; import static utils.matchers.ResultContainsExactly.containsExactly;
import static utils.matchers.ResultContainsNoErrorInMethod.doesNotContain;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -49,144 +48,30 @@ public class MemoryLeakTest {
false); false);
} }
@Test @Test
public void whenInferRunsOnLayoutSubviewsThenMLIsNotFound() public void matchErrors()
throws InterruptedException, IOException, InferException { throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd); InferResults inferResults = InferRunner.runInferObjC(inferCmd);
String[] procedures = {
"test",
"measureFrameSizeForText",
"test1:",
"createCloseCrossGlyph:",
"test2:",
"regularLeak",
"blockCapturedVarLeak",
// TODO: don't report on this test
"blockFreeNoLeakTODO"
};
assertThat( assertThat(
"Results should not contain memory leak", "Results should contain the expected memory leak",
inferResults, inferResults,
doesNotContain( containsExactly(
MEMORY_LEAK, MEMORY_LEAK,
memory_leak_file, memory_leak_file,
"layoutSubviews")); procedures
}
@Test
public void whenInferRunsOnTestThenMLIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should contain memory leak",
inferResults,
contains(
MEMORY_LEAK,
memory_leak_file,
"test"
)
);
}
@Test
public void whenInferRunsOnMeasureFrameSizeForTextThenMLIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should contain memory leak",
inferResults,
contains(
MEMORY_LEAK,
memory_leak_file,
"measureFrameSizeForText"
)
);
}
@Test
public void whenInferRunsOnMeasureFrameSizeForTextNoLeakThenMLIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should not contain a memory leak",
inferResults,
doesNotContain(
MEMORY_LEAK,
memory_leak_file,
"measureFrameSizeForTextNoLeak"));
}
@Test
public void whenInferRunsOnTest1ThenMLIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should contain memory leak",
inferResults,
contains(
MEMORY_LEAK,
memory_leak_file,
"test1:"
)
);
}
@Test
public void whenInferRunsOnTest1NoLeakThenMLIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should not contain a memory leak",
inferResults,
doesNotContain(
MEMORY_LEAK,
memory_leak_file,
"test1NoLeak"));
}
@Test
public void whenInferRunsOn_createCloseCrossGlyphWithRectThenMLIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should contain memory leak",
inferResults,
contains(
MEMORY_LEAK,
memory_leak_file,
"createCloseCrossGlyph:"
)
);
}
@Test
public void whenInferRunsOn_createCloseCrossGlyphWithRectNoLeakThenMLIsNotFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should not contain a memory leak",
inferResults,
doesNotContain(
MEMORY_LEAK,
memory_leak_file,
"createCloseCrossGlyphNoLeak:"));
}
@Test
public void whenInferRunsOnTest2ThenMLIFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should contain memory leak",
inferResults,
contains(
MEMORY_LEAK,
memory_leak_file,
"test2:"
) )
); );
} }
@Test
public void whenInferTest2NoLakNoLeakThenMLIsNotFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should not contain a memory leak",
inferResults,
doesNotContain(
MEMORY_LEAK,
memory_leak_file,
"test2NoLeak"));
}
} }

Loading…
Cancel
Save