Skip whitelisted functions form trace

Reviewed By: akotulski

Differential Revision: D3335216

fbshipit-source-id: 3bda232
master
Dulma Churchill 9 years ago committed by Facebook Github Bot 7
parent 25578de26d
commit de615594df

@ -106,6 +106,20 @@ let pname_is_cpp_model callee_pname =>
| None => false | None => false
}; };
let is_whitelisted_cpp_method method_name =>
IList.exists
(
fun whitelisting_class =>
IList.for_all
(
fun whitelisting_class_substring =>
Utils.string_contains whitelisting_class_substring method_name
)
whitelisting_class
)
Config.whitelisted_cpp_methods;
let stats () => { let stats () => {
let stats = Procname.Hash.stats attr_tbl; let stats = Procname.Hash.stats attr_tbl;
let {Hashtbl.num_bindings: num_bindings, num_buckets, max_bucket_length} = stats; let {Hashtbl.num_bindings: num_bindings, num_buckets, max_bucket_length} = stats;

@ -36,4 +36,6 @@ let get_correct_type_from_objc_class_name: Mangled.t => option Sil.typ;
/** Returns true if the method is defined as a C++ model */ /** Returns true if the method is defined as a C++ model */
let pname_is_cpp_model: Procname.t => bool; let pname_is_cpp_model: Procname.t => bool;
let is_whitelisted_cpp_method : string => bool;
let stats: unit => (string, Yojson.json); let stats: unit => (string, Yojson.json);

@ -203,6 +203,16 @@ let cpp_models_dir =
"models/cpp/include" in "models/cpp/include" in
cpp_models_dir cpp_models_dir
let whitelisted_cpp_methods = [
["std"; "move"];
["google"; "CheckNotNull"];
["google"; "GetReferenceableValue"];
["google"; "Check_NEImpl"];
["google"; "Check_LEImpl"];
["google"; "Check_GTImpl"];
["google"; "Check_EQImpl"]
]
let os_type = match Sys.os_type with let os_type = match Sys.os_type with
| "Win32" -> Win32 | "Win32" -> Win32
| "Cygwin" -> Cygwin | "Cygwin" -> Cygwin

@ -70,6 +70,7 @@ val max_recursion : int
val meet_level : int val meet_level : int
val models_dir : string val models_dir : string
val cpp_models_dir : string val cpp_models_dir : string
val whitelisted_cpp_methods : string list list
val nsnotification_center_checker_backend : bool val nsnotification_center_checker_backend : bool
val objc_method_call_semantics : bool val objc_method_call_semantics : bool
val os_type : os_type val os_type : os_type

@ -665,7 +665,8 @@ let prop_set_exn pname prop se_exn =
(** Include a subtrace for a procedure call if the callee is not a model. *) (** Include a subtrace for a procedure call if the callee is not a model. *)
let include_subtrace callee_pname = let include_subtrace callee_pname =
Specs.get_origin callee_pname <> DB.Models && Specs.get_origin callee_pname <> DB.Models &&
not (AttributesTable.pname_is_cpp_model callee_pname) not (AttributesTable.pname_is_cpp_model callee_pname) &&
not (AttributesTable.is_whitelisted_cpp_method (Procname.to_string callee_pname))
(** combine the spec's post with a splitting and actual precondition *) (** combine the spec's post with a splitting and actual precondition *)
let combine let combine

@ -115,14 +115,6 @@ let google_LogMessageFatal = "google::LogMessageFatal_LogMessageFatal"
let google_MakeCheckOpString = "google::MakeCheckOpString" let google_MakeCheckOpString = "google::MakeCheckOpString"
let google_whitelisting_functions = [
"CheckNotNull";
"GetReferenceableValue";
"Check_NEImpl";
"Check_LEImpl";
"Check_GTImpl";
"Check_EQImpl"]
let pseudo_object_type = "<pseudo-object type>" let pseudo_object_type = "<pseudo-object type>"
let count = "count" let count = "count"

@ -117,8 +117,6 @@ val google_LogMessageFatal : string
val google_MakeCheckOpString : string val google_MakeCheckOpString : string
val google_whitelisting_functions : string list
val pseudo_object_type : string val pseudo_object_type : string
val count : string val count : string

@ -152,13 +152,8 @@ struct
(* named_decl_info.ni_name has name without template parameters.*) (* named_decl_info.ni_name has name without template parameters.*)
(* It makes it possible to capture whole family of function instantiations*) (* It makes it possible to capture whole family of function instantiations*)
(* to be named the same *) (* to be named the same *)
let fun_name = name_info.Clang_ast_t.ni_name in let name = Ast_utils.get_qualified_name name_info in
let qual_name = name_info.Clang_ast_t.ni_qual_name in AttributesTable.is_whitelisted_cpp_method name
let top_qual = IList.hd (IList.rev qual_name) in
(* Always translate std::move so that it can be analyzed *)
top_qual = "std" && fun_name = "move" ||
top_qual = "google" &&
IList.mem (=) fun_name CFrontend_config.google_whitelisting_functions
| _ -> false in | _ -> false in
let never_translate_decl = match dec with let never_translate_decl = match dec with
| Clang_ast_t.FunctionDecl (_, name_info, _, _) | Clang_ast_t.FunctionDecl (_, name_info, _, _)

@ -0,0 +1,34 @@
/*
* 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 <memory>
struct Person {
std::unique_ptr<int> age{new int(35)};
std::unique_ptr<int> move_age() { return std::move(age); }
int access_age() { return *age; }
};
int deref_after_move_crash() {
Person p;
auto x = p.move_age();
*x;
return p.access_age();
}
int deref_ok() {
Person p;
return p.access_age();
}
int deref_after_move_ok() {
Person p;
auto x = p.move_age();
return *x;
}

@ -0,0 +1,63 @@
/*
* 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.
*/
package endtoend.cpp;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsExactly.containsExactly;
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 DerefAfterMoveTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/errors/smart_ptr/deref_after_move_example.cpp";
private static ImmutableList<String> 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.createCPPInferCommand(folder, FILE);
}
@Test
public void whenInferRunsOngetPersonAgeNPEIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferC(inferCmd);
String[] procedures = {
"deref_after_move_crash",
};
assertThat(
"Results should contain the expected npe",
inferResults,
containsExactly(
NULL_DEREFERENCE,
FILE,
procedures
)
);
}
}
Loading…
Cancel
Save