From 60d9a19ae0606432be704bbb8feca026ef45999e Mon Sep 17 00:00:00 2001 From: Dulma Churchill Date: Tue, 31 May 2016 08:56:05 -0700 Subject: [PATCH] Fix bucketing for variables passed by reference Reviewed By: akotulski Differential Revision: D3358473 fbshipit-source-id: ed7a509 --- infer/src/backend/errdesc.ml | 11 ++++ .../cpp/errors/npe/npe_added_to_b1.cpp | 30 +++++++++ .../tests/endtoend/cpp/NPEAddedToB1Test.java | 63 +++++++++++++++++++ infer/tests/utils/InferRunner.java | 49 ++++++++++++++- 4 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 infer/tests/codetoanalyze/cpp/errors/npe/npe_added_to_b1.cpp create mode 100644 infer/tests/endtoend/cpp/NPEAddedToB1Test.java diff --git a/infer/src/backend/errdesc.ml b/infer/src/backend/errdesc.ml index 5f7df1798..ddc75c8e3 100644 --- a/infer/src/backend/errdesc.ml +++ b/infer/src/backend/errdesc.ml @@ -693,6 +693,14 @@ let explain_dexp_access prop dexp is_nullable = (L.d_str "lookup: case not matched on Darray "; Sil.d_sexp se1; L.d_str " "; Sil.d_sexp se2; L.d_ln()); None) + | Sil.Darrow ((Sil.Dpvaraddr pvar), f) -> + (match lookup (Sil.Dpvaraddr pvar) with + | None -> None + | Some Sil.Estruct (fsel, _) -> + lookup_fld fsel f + | Some _ -> + if verbose then (L.d_str "lookup: case not matched on Darrow "; L.d_ln ()); + None) | Sil.Darrow (de1, f) -> (match lookup (Sil.Dderef de1) with | None -> None @@ -730,6 +738,9 @@ let explain_dexp_access prop dexp is_nullable = when method_of_pointer_wrapper pname -> if verbose then (L.d_strln "lookup: found Dretcall "); Some (Sil.Eexp (Sil.Const c, Sil.Ireturn_from_pointer_wrapper_call loc.Location.line)) + | Sil.Dpvaraddr pvar -> + (L.d_strln ("lookup: found Dvaraddr " ^ Sil.dexp_to_string (Sil.Dpvaraddr pvar))); + find_ptsto (Sil.Lvar pvar) | de -> if verbose then (L.d_strln ("lookup: unknown case not matched " ^ Sil.dexp_to_string de)); None in diff --git a/infer/tests/codetoanalyze/cpp/errors/npe/npe_added_to_b1.cpp b/infer/tests/codetoanalyze/cpp/errors/npe/npe_added_to_b1.cpp new file mode 100644 index 000000000..3e327d9e7 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/errors/npe/npe_added_to_b1.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016 - 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 + +int deref_ref(std::shared_ptr& p) { return *p; } + +int causes_npe() { + std::shared_ptr x; + return deref_ref(x); +} + +class Person { + public: + Person() { f1 = nullptr; } + int* f1; +}; + +int deref_person(Person& p) { return *(p.f1); } + +int causes_npe_person() { + Person p; + return deref_person(p); +} diff --git a/infer/tests/endtoend/cpp/NPEAddedToB1Test.java b/infer/tests/endtoend/cpp/NPEAddedToB1Test.java new file mode 100644 index 000000000..7e84b0c2a --- /dev/null +++ b/infer/tests/endtoend/cpp/NPEAddedToB1Test.java @@ -0,0 +1,63 @@ +/* + * 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.cpp; + +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 org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.IOException; + +import utils.DebuggableTemporaryFolder; +import utils.InferException; +import utils.InferResults; +import utils.InferRunner; + +public class NPEAddedToB1Test { + + public static final String FILE = + "infer/tests/codetoanalyze/cpp/errors/npe/npe_added_to_b1.cpp"; + + private static ImmutableList inferCmd; + + public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE"; + + @ClassRule + public static DebuggableTemporaryFolder folder = + new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createCPPInferCommandFilter(folder, FILE); + } + + @Test + public void whenInferRunsOnMethodCallThenNoNPEFound() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferCPP(inferCmd); + String[] procedures = {"causes_npe", "causes_npe_person"}; + assertThat( + "Results should contain " + NULL_DEREFERENCE, + inferResults, + containsExactly( + NULL_DEREFERENCE, + FILE, + procedures + ) + ); + } +} diff --git a/infer/tests/utils/InferRunner.java b/infer/tests/utils/InferRunner.java index ca47ddad2..9d7b3859d 100644 --- a/infer/tests/utils/InferRunner.java +++ b/infer/tests/utils/InferRunner.java @@ -261,7 +261,8 @@ public class InferRunner { @Nullable String ml_buckets, boolean arc, boolean headers, - boolean testingMode) { + boolean testingMode, + boolean filter) { File resultsDir = createResultsDir(folder); String resultsDirName = resultsDir.getAbsolutePath(); InferRunner.bugsFile = new File(resultsDir, BUGS_FILE_NAME); @@ -288,10 +289,15 @@ public class InferRunner { if (testingMode) { testingModeOption.add("--testing_mode"); } + ImmutableList.Builder doNotFilterOption = + new ImmutableList.Builder<>(); + if (!filter) { + doNotFilterOption.add("--no-filtering"); + } ImmutableList inferCmd = new ImmutableList.Builder() .add("infer") .add("--no-progress-bar") - .add("--no-filtering") + .addAll(doNotFilterOption.build()) .add("--out") .add(resultsDirName) .addAll(testingModeOption.build()) @@ -304,6 +310,29 @@ public class InferRunner { return inferCmd; } + public static ImmutableList createClangInferCommand( + TemporaryFolder folder, + String sourceFile, + Language lang, + boolean analyze, + @Nullable String isysroot, + @Nullable String ml_buckets, + boolean arc, + boolean headers, + boolean testingMode) { + return createClangInferCommand( + folder, + sourceFile, + lang, + analyze, + isysroot, + ml_buckets, + arc, + headers, + testingMode, + false); + } + public static ImmutableList createClangInferCommand( TemporaryFolder folder, String sourceFile, @@ -446,6 +475,22 @@ public class InferRunner { false); } + public static ImmutableList createCPPInferCommandFilter( + TemporaryFolder folder, + String sourceFile) throws IOException, InterruptedException { + return createClangInferCommand( + folder, + sourceFile, + Language.CPP, + true, + null, + null, + false, + false, + false, + true); + } + public static ImmutableList createObjCInferCommand( TemporaryFolder folder, String sourceFile) throws IOException, InterruptedException {