diff --git a/infer/src/IR/Exp.ml b/infer/src/IR/Exp.ml index cc6316565..3f2fcb407 100644 --- a/infer/src/IR/Exp.ml +++ b/infer/src/IR/Exp.ml @@ -254,12 +254,12 @@ let rec pp_ pe pp_t f e = subtype -and pp_captured_var pe pp_t f (exp, var, _) = +and pp_captured_var pe pp_t f (exp, var, typ) = match exp with | Lvar evar when Pvar.equal var evar -> F.fprintf f "%a" (Pvar.pp pe) var | _ -> - F.fprintf f "(%a %a)" (pp_ pe pp_t) exp (Pvar.pp pe) var + F.fprintf f "(%a %a:%a)" (pp_ pe pp_t) exp (Pvar.pp pe) var (Typ.pp pe) typ let pp_printenv pe pp_typ f e = pp_ pe (pp_typ pe) f e diff --git a/infer/src/backend/RetainCycles.ml b/infer/src/backend/RetainCycles.ml index 705f3e9ed..fa2ab60ab 100644 --- a/infer/src/backend/RetainCycles.ml +++ b/infer/src/backend/RetainCycles.ml @@ -67,7 +67,14 @@ let get_cycle root prop = | Exp.Closure {captured_vars} (* will turn on in prod when false positives have been addressed *) when Config.debug_exceptions -> - List.find ~f:(fun (e, _, _) -> Exp.equal e root_node.rc_node_exp) captured_vars + List.find + ~f:(fun (e, _, typ) -> + match typ.Typ.desc with + | Typ.Tptr (_, Typ.Pk_objc_weak) | Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) -> + false + | _ -> + Exp.equal e root_node.rc_node_exp ) + captured_vars |> Option.map ~f:snd3 | _ -> None diff --git a/infer/tests/codetoanalyze/objc/errors/issues.exp b/infer/tests/codetoanalyze/objc/errors/issues.exp index 471f4fd82..3243d8194 100644 --- a/infer/tests/codetoanalyze/objc/errors/issues.exp +++ b/infer/tests/codetoanalyze/objc/errors/issues.exp @@ -30,7 +30,7 @@ codetoanalyze/objc/errors/field_superclass/SubtypingExample.m, subtyping_test, 0 codetoanalyze/objc/errors/initialization/struct_initlistexpr.c, field_set_correctly, 2, DIVIDE_BY_ZERO, [start of procedure field_set_correctly()] codetoanalyze/objc/errors/initialization/struct_initlistexpr.c, implicit_expr_set_correctly, 3, DIVIDE_BY_ZERO, [start of procedure implicit_expr_set_correctly()] codetoanalyze/objc/errors/initialization/struct_initlistexpr.c, point_coords_set_correctly, 2, DIVIDE_BY_ZERO, [start of procedure point_coords_set_correctly()] -codetoanalyze/objc/errors/memory_leaks_benchmark/RetainCycleBlocks.m, main, 2, RETAIN_CYCLE, [start of procedure main(),start of procedure retain_self_in_block,return from a call to RCBlock_retain_self_in_block] +codetoanalyze/objc/errors/memory_leaks_benchmark/RetainCycleBlocks.m, call_retain_self_in_block_cycle, 2, RETAIN_CYCLE, [start of procedure call_retain_self_in_block_cycle(),start of procedure retain_self_in_block,return from a call to RCBlock_retain_self_in_block] codetoanalyze/objc/errors/memory_leaks_benchmark/retain_cycle.m, strongcycle, 6, RETAIN_CYCLE, [start of procedure strongcycle()] codetoanalyze/objc/errors/memory_leaks_benchmark/retain_cycle2.m, strongcycle2, 4, RETAIN_CYCLE, [start of procedure strongcycle2(),start of procedure init,return from a call to Parent_init,start of procedure init,return from a call to Child_init,start of procedure setChild:,return from a call to Parent_setChild:,start of procedure setParent:,return from a call to Child_setParent:] codetoanalyze/objc/errors/npe/UpdateDict.m, add_nil_in_dict, 10, NULL_DEREFERENCE, [start of procedure add_nil_in_dict(),Skipping dictionaryWithObjectsAndKeys:: function or method not found] diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/RetainCycleBlocks.m b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/RetainCycleBlocks.m index e64000e19..c817e24a3 100644 --- a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/RetainCycleBlocks.m +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/RetainCycleBlocks.m @@ -36,10 +36,25 @@ typedef void (^MyHandler)(RCBlock* name); }; } +- (void)retain_weak_self_in_block { + __weak typeof(self) weak_self = self; + self.handler = ^(RCBlock* b) { + __strong typeof(self) strong_self = weak_self; + if (strong_self) + strong_self->_child = b; + }; +} + @end -int main() { +int call_retain_self_in_block_cycle() { RCBlock* c = [[RCBlock alloc] init]; [c retain_self_in_block]; return 0; } + +int call_retain_weak_self_in_block_no_cycle() { + RCBlock* c = [[RCBlock alloc] init]; + [c retain_weak_self_in_block]; + return 0; +} diff --git a/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot b/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot index 65cf06f5f..863ae5339 100644 --- a/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot +++ b/infer/tests/codetoanalyze/objc/frontend/block/retain_cycle.m.dot @@ -41,7 +41,7 @@ digraph cfg { "capture#A#instance.d411336575e4bf632a1828f5f5979726_2" [label="2: Exit A_capture \n " color=yellow style=filled] -"capture#A#instance.d411336575e4bf632a1828f5f5979726_3" [label="3: Message Call: sHandler: \n n$0=*&self:A* [line 47, column 4]\n n$1=*n$0._b:B* [line 47, column 4]\n n$2=*&self:A* [line 47, column 16]\n _fun_B_sHandler:(n$1:B*,(_fun_objc_blockA_capture_1,(n$2 &self)):_fn_(*)) virtual block_params [line 47, column 3]\n " shape="box"] +"capture#A#instance.d411336575e4bf632a1828f5f5979726_3" [label="3: Message Call: sHandler: \n n$0=*&self:A* [line 47, column 4]\n n$1=*n$0._b:B* [line 47, column 4]\n n$2=*&self:A* [line 47, column 16]\n _fun_B_sHandler:(n$1:B*,(_fun_objc_blockA_capture_1,(n$2 &self:A*)):_fn_(*)) virtual block_params [line 47, column 3]\n " shape="box"] "capture#A#instance.d411336575e4bf632a1828f5f5979726_3" -> "capture#A#instance.d411336575e4bf632a1828f5f5979726_2" ; diff --git a/infer/tests/codetoanalyze/objc/shared/block/BlockVar.m.dot b/infer/tests/codetoanalyze/objc/shared/block/BlockVar.m.dot index 74d817648..2b65c889a 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/BlockVar.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/BlockVar.m.dot @@ -85,7 +85,7 @@ digraph cfg { "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_3" -> "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_2" ; -"blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_4" [label="4: DeclStmt \n n$13=*&x:int* [line 33, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_blockPostBad_2,(n$13 &x)) [line 33, column 3]\n " shape="box"] +"blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_4" [label="4: DeclStmt \n n$13=*&x:int* [line 33, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_blockPostBad_2,(n$13 &x:int*)) [line 33, column 3]\n " shape="box"] "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_4" -> "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_3" ; @@ -104,7 +104,7 @@ digraph cfg { "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_3" -> "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_2" ; -"blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_4" [label="4: DeclStmt \n n$18=*&x:int* [line 42, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_blockPostOk_3,(n$18 &x)) [line 42, column 3]\n " shape="box"] +"blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_4" [label="4: DeclStmt \n n$18=*&x:int* [line 42, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_blockPostOk_3,(n$18 &x:int*)) [line 42, column 3]\n " shape="box"] "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_4" -> "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_3" ; @@ -127,7 +127,7 @@ digraph cfg { "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_3" -> "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_2" ; -"capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_4" [label="4: DeclStmt \n n$22=*&x:int* [line 50, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_capturedNullDeref_4,(n$22 &x)) [line 50, column 3]\n " shape="box"] +"capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_4" [label="4: DeclStmt \n n$22=*&x:int* [line 50, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_capturedNullDeref_4,(n$22 &x:int*)) [line 50, column 3]\n " shape="box"] "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_4" -> "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_3" ; @@ -150,7 +150,7 @@ digraph cfg { "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_4" -> "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_3" ; -"capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_5" [label="5: DeclStmt \n n$27=*&x:int* [line 59, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_capturedNoNullDeref_5,(n$27 &x)) [line 59, column 3]\n " shape="box"] +"capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_5" [label="5: DeclStmt \n n$27=*&x:int* [line 59, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar_capturedNoNullDeref_5,(n$27 &x:int*)) [line 59, column 3]\n " shape="box"] "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_5" -> "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_4" ; diff --git a/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot b/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot index 37898ce8d..3737082fe 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/Blocks_as_parameters.m.dot @@ -11,7 +11,7 @@ digraph cfg { "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_3" -> "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_2" ; -"f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_4" [label="4: Message Call: foo:and: \n n$2=*&self:B* [line 25, column 10]\n n$3=*n$2.h:int [line 25, column 10]\n n$4=*&self:B* const [line 26, column 11]\n _fun_B_foo:and:(n$3:int,(_fun_objc_blockB_f_1,(n$4 &self)):_fn_(*)) block_params [line 25, column 3]\n " shape="box"] +"f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_4" [label="4: Message Call: foo:and: \n n$2=*&self:B* [line 25, column 10]\n n$3=*n$2.h:int [line 25, column 10]\n n$4=*&self:B* const [line 26, column 11]\n _fun_B_foo:and:(n$3:int,(_fun_objc_blockB_f_1,(n$4 &self:B* const )):_fn_(*)) block_params [line 25, column 3]\n " shape="box"] "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_4" -> "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_3" ; diff --git a/infer/tests/codetoanalyze/objc/shared/block/block.m.dot b/infer/tests/codetoanalyze/objc/shared/block/block.m.dot index 036b7f553..b57df0a74 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/block.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/block.m.dot @@ -49,7 +49,7 @@ digraph cfg { "main1.38f534a9576db7ec6ebcbca8c111f942_7" -> "main1.38f534a9576db7ec6ebcbca8c111f942_6" ; -"main1.38f534a9576db7ec6ebcbca8c111f942_8" [label="8: BinaryOperatorStmt: Assign \n n$9=*&x:int [line 18, column 14]\n *&addblock:_fn_(*)=(_fun_objc_blockmain1_2,(n$9 &x)) [line 18, column 3]\n " shape="box"] +"main1.38f534a9576db7ec6ebcbca8c111f942_8" [label="8: BinaryOperatorStmt: Assign \n n$9=*&x:int [line 18, column 14]\n *&addblock:_fn_(*)=(_fun_objc_blockmain1_2,(n$9 &x:int)) [line 18, column 3]\n " shape="box"] "main1.38f534a9576db7ec6ebcbca8c111f942_8" -> "main1.38f534a9576db7ec6ebcbca8c111f942_7" ; @@ -76,7 +76,7 @@ digraph cfg { "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_4" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_3" ; -"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" [label="5: BinaryOperatorStmt: Assign \n n$15=*&x:int [line 24, column 17]\n n$16=*&bla:int [line 24, column 17]\n *&addblock2:_fn_(*)=(_fun_objc_blockobjc_blockmain1_2_3,(n$15 &x),(n$16 &bla)) [line 24, column 5]\n " shape="box"] +"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" [label="5: BinaryOperatorStmt: Assign \n n$15=*&x:int [line 24, column 17]\n n$16=*&bla:int [line 24, column 17]\n *&addblock2:_fn_(*)=(_fun_objc_blockobjc_blockmain1_2_3,(n$15 &x:int),(n$16 &bla:int)) [line 24, column 5]\n " shape="box"] "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_4" ; diff --git a/infer/tests/codetoanalyze/objc/shared/block/block_no_args.m.dot b/infer/tests/codetoanalyze/objc/shared/block/block_no_args.m.dot index e67f08dee..b96e0e78f 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/block_no_args.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/block_no_args.m.dot @@ -44,7 +44,7 @@ digraph cfg { "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_11" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_10" ; -"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_12" [label="12: BinaryOperatorStmt: Assign \n n$5=*&z:int [line 25, column 7]\n *&b:_fn_(*)=(_fun_objc_blockMy_manager_m_1,(n$5 &z)) [line 25, column 3]\n " shape="box"] +"m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_12" [label="12: BinaryOperatorStmt: Assign \n n$5=*&z:int [line 25, column 7]\n *&b:_fn_(*)=(_fun_objc_blockMy_manager_m_1,(n$5 &z:int)) [line 25, column 3]\n " shape="box"] "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_12" -> "m#My_manager#instance.e773f849d062cb9801497b62f5c98f5e_11" ; diff --git a/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot b/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot index 4b55a8855..f75c3b082 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/block_release.m.dot @@ -32,7 +32,7 @@ digraph cfg { "blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_8" -> "blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_5" ; "blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_8" -> "blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_6" ; -"blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_9" [label="9: BinaryOperatorStmt: Assign \n n$5=*&newImage:CGImage* [line 25, column 7]\n *&b:_fn_(*)=(_fun_objc_blockMy_manager_blockReleaseTODO_1,(n$5 &newImage)) [line 25, column 3]\n " shape="box"] +"blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_9" [label="9: BinaryOperatorStmt: Assign \n n$5=*&newImage:CGImage* [line 25, column 7]\n *&b:_fn_(*)=(_fun_objc_blockMy_manager_blockReleaseTODO_1,(n$5 &newImage:CGImage*)) [line 25, column 3]\n " shape="box"] "blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_9" -> "blockReleaseTODO#My_manager#instance.8c1d633cf596e86a307167d9425628a8_8" ; diff --git a/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot b/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot index 8d02d7d06..c276306f4 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/dispatch.m.dot @@ -37,7 +37,7 @@ digraph cfg { "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_3" -> "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_2" ; -"block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_4" [label="4: Call _fun__dispatch_once \n n$6=*&a:DispatchA* [line 39, column 24]\n _fun__dispatch_once(&#GB$DispatchA_block_attribute_once:long*,(_fun_objc_blockDispatchA_block_attribute_2,(n$6 &a)):_fn_(*)) block_params [line 39, column 3]\n " shape="box"] +"block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_4" [label="4: Call _fun__dispatch_once \n n$6=*&a:DispatchA* [line 39, column 24]\n _fun__dispatch_once(&#GB$DispatchA_block_attribute_once:long*,(_fun_objc_blockDispatchA_block_attribute_2,(n$6 &a:DispatchA*)):_fn_(*)) block_params [line 39, column 3]\n " shape="box"] "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_4" -> "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_3" ; diff --git a/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m.dot b/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m.dot index fd6e33390..505ae4771 100644 --- a/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/MemoryLeakExample.m.dot @@ -188,7 +188,7 @@ digraph cfg { "blockCapturedVarLeak#MemoryLeakExample#instance.53bb018bc84d6a696dc756e20b5b3f52_3" -> "blockCapturedVarLeak#MemoryLeakExample#instance.53bb018bc84d6a696dc756e20b5b3f52_2" ; -"blockCapturedVarLeak#MemoryLeakExample#instance.53bb018bc84d6a696dc756e20b5b3f52_4" [label="4: DeclStmt \n n$42=*&x:int* [line 96, column 22]\n *&blk:_fn_(*)=(_fun_objc_blockMemoryLeakExample_blockCapturedVarLeak_1,(n$42 &x)) [line 96, column 3]\n " shape="box"] +"blockCapturedVarLeak#MemoryLeakExample#instance.53bb018bc84d6a696dc756e20b5b3f52_4" [label="4: DeclStmt \n n$42=*&x:int* [line 96, column 22]\n *&blk:_fn_(*)=(_fun_objc_blockMemoryLeakExample_blockCapturedVarLeak_1,(n$42 &x:int*)) [line 96, column 3]\n " shape="box"] "blockCapturedVarLeak#MemoryLeakExample#instance.53bb018bc84d6a696dc756e20b5b3f52_4" -> "blockCapturedVarLeak#MemoryLeakExample#instance.53bb018bc84d6a696dc756e20b5b3f52_3" ; @@ -211,7 +211,7 @@ digraph cfg { "blockFreeNoLeakTODO#MemoryLeakExample#instance.745cca07ccdb517734d79c9d7a1eaed8_3" -> "blockFreeNoLeakTODO#MemoryLeakExample#instance.745cca07ccdb517734d79c9d7a1eaed8_2" ; -"blockFreeNoLeakTODO#MemoryLeakExample#instance.745cca07ccdb517734d79c9d7a1eaed8_4" [label="4: DeclStmt \n n$49=*&x:int* [line 105, column 22]\n *&blk:_fn_(*)=(_fun_objc_blockMemoryLeakExample_blockFreeNoLeakTODO_2,(n$49 &x)) [line 105, column 3]\n " shape="box"] +"blockFreeNoLeakTODO#MemoryLeakExample#instance.745cca07ccdb517734d79c9d7a1eaed8_4" [label="4: DeclStmt \n n$49=*&x:int* [line 105, column 22]\n *&blk:_fn_(*)=(_fun_objc_blockMemoryLeakExample_blockFreeNoLeakTODO_2,(n$49 &x:int*)) [line 105, column 3]\n " shape="box"] "blockFreeNoLeakTODO#MemoryLeakExample#instance.745cca07ccdb517734d79c9d7a1eaed8_4" -> "blockFreeNoLeakTODO#MemoryLeakExample#instance.745cca07ccdb517734d79c9d7a1eaed8_3" ;