diff --git a/infer/src/checkers/uninit.ml b/infer/src/checkers/uninit.ml index 3aeb08dc9..f85dad73a 100644 --- a/infer/src/checkers/uninit.ml +++ b/infer/src/checkers/uninit.ml @@ -86,7 +86,8 @@ module TransferFunctions (CFG : ProcCfg.S) = struct let remove_fields tenv base uninit_vars = match base with - | _, {Typ.desc= Tptr ({Typ.desc= Tstruct name_struct}, _)} -> ( + | _, {Typ.desc= Tptr ({Typ.desc= Tstruct name_struct}, _)} | _, {Typ.desc= Tstruct name_struct} + -> ( match Tenv.lookup tenv name_struct with | Some {fields} -> List.fold @@ -106,10 +107,16 @@ module TransferFunctions (CFG : ProcCfg.S) = struct (instr: HilInstr.t) = match instr with | Assign - ( (((_, lhs_typ), _) as lhs_ap) + ( (((lhs_var, lhs_typ), apl) as lhs_ap) , HilExp.AccessPath (((rhs_var, rhs_typ) as rhs_base), al) , loc ) -> - let uninit_vars = D.remove lhs_ap astate.uninit_vars in + let uninit_vars' = D.remove lhs_ap astate.uninit_vars in + let uninit_vars = + if Int.equal (List.length apl) 0 then + (* if we assign to the root of a struct then we need to remove all the fields *) + remove_fields tenv (lhs_var, lhs_typ) uninit_vars' + else uninit_vars' + in let prepost = if FormalMap.is_formal rhs_base (fst extras) && match rhs_typ.desc with Typ.Tptr _ -> true | _ -> false diff --git a/infer/tests/codetoanalyze/objc/uninit/uninit.m b/infer/tests/codetoanalyze/objc/uninit/uninit.m new file mode 100644 index 000000000..17404fa8c --- /dev/null +++ b/infer/tests/codetoanalyze/objc/uninit/uninit.m @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +#include + +@interface A : NSObject + +- (CGSize)sizeThatFits:(int)x; +- (int)init_var_ok; + +@end + +@implementation A + +- (CGSize)sizeThatFits:(int)x { + + CGSize s = CGSizeMake(x, x); + + return s; +} + +- (int)init_var_ok { + const CGSize labelSize = [self sizeThatFits:10]; + + return labelSize.height; // Here we should not report uninit +} + +@end