From d66261a1f4246bf3199ef0c9bc8d99272f3fb3d4 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Wed, 9 Dec 2015 15:05:12 -0800 Subject: [PATCH] Do not reuse Undef function values Summary: Change eradicate handling of complex values so that an unknown function that has an existing mapping to Undef is treated as if there was no existing mapping. Without this change, joining control-flow branches where one called a function and the other did not resulted in a mapping to Undef. Later calls to the function would then reuse the Undef mapping. public Reviewed By: cristianoc Differential Revision: D2695548 fb-gh-sync-id: ab69c47 --- infer/src/checkers/typeCheck.ml | 11 ++-- .../eradicate/NoReuseUndefFunctionValues.java | 34 ++++++++++++ .../NoReuseUndefFunctionValuesTest.java | 52 +++++++++++++++++++ 3 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 infer/tests/codetoanalyze/java/eradicate/NoReuseUndefFunctionValues.java create mode 100644 infer/tests/endtoend/java/eradicate/NoReuseUndefFunctionValuesTest.java diff --git a/infer/src/checkers/typeCheck.ml b/infer/src/checkers/typeCheck.ml index b00d2e8ce..70d23d7ce 100644 --- a/infer/src/checkers/typeCheck.ml +++ b/infer/src/checkers/typeCheck.ml @@ -313,9 +313,14 @@ let typecheck_instr ext calls_this checks (node: Cfg.Node.t) idenv get_proc_desc | None -> default | Some exp_str -> let pvar = Sil.mk_pvar (Mangled.from_string exp_str) curr_pname in - let already_in_typestate = TypeState.lookup_pvar pvar typestate <> None in - - if is_assignment && already_in_typestate + let already_defined_in_typestate = + match TypeState.lookup_pvar pvar typestate with + | Some (_, ta, _) -> + not (TypeOrigin.equal TypeOrigin.Undef (TypeAnnotation.get_origin ta)) + | None -> + false in + + if is_assignment && already_defined_in_typestate then default (* Don't overwrite pvar representing result of function call. *) else Sil.Lvar pvar, typestate end diff --git a/infer/tests/codetoanalyze/java/eradicate/NoReuseUndefFunctionValues.java b/infer/tests/codetoanalyze/java/eradicate/NoReuseUndefFunctionValues.java new file mode 100644 index 000000000..92c4ae78a --- /dev/null +++ b/infer/tests/codetoanalyze/java/eradicate/NoReuseUndefFunctionValues.java @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2015 - 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. +*/ + +package codetoanalyze.java.eradicate; + +import javax.annotation.Nullable; + +public class NoReuseUndefFunctionValues { + + Object mObject1; + Object mObject2; + + native Object create(); + + public NoReuseUndefFunctionValues(@Nullable Object object) { + if (object != null) { + this.mObject1 = object; + } else { + this.mObject1 = this.create(); + } + if (object != null) { + this.mObject2 = object; + } else { + this.mObject2 = this.create(); + } + } + +} diff --git a/infer/tests/endtoend/java/eradicate/NoReuseUndefFunctionValuesTest.java b/infer/tests/endtoend/java/eradicate/NoReuseUndefFunctionValuesTest.java new file mode 100644 index 000000000..62a35ffbc --- /dev/null +++ b/infer/tests/endtoend/java/eradicate/NoReuseUndefFunctionValuesTest.java @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2015 - 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. +*/ + +package endtoend.java.eradicate; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.ResultContainsExactly.containsExactly; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; + +import utils.InferException; +import utils.InferResults; + +public class NoReuseUndefFunctionValuesTest { + + public static final String SOURCE_FILE = + "infer/tests/codetoanalyze/java/eradicate/NoReuseUndefFunctionValues.java"; + + public static final String FIELD_NOT_INITIALIZED = + "ERADICATE_FIELD_NOT_INITIALIZED"; + + private static InferResults inferResults; + + @BeforeClass + public static void loadResults() throws InterruptedException, IOException { + inferResults = + InferResults.loadEradicateResults(NoReuseUndefFunctionValuesTest.class, SOURCE_FILE); + } + + @Test + public void matchErrors() + throws IOException, InterruptedException, InferException { + String[] noMethods = {}; + assertThat( + "Results should contain " + FIELD_NOT_INITIALIZED, + inferResults, + containsExactly( + FIELD_NOT_INITIALIZED, + SOURCE_FILE, + noMethods)); + } + +}