diff --git a/infer/src/backend/config.ml b/infer/src/backend/config.ml index c706ee7fd..6e93ba193 100644 --- a/infer/src/backend/config.ml +++ b/infer/src/backend/config.ml @@ -54,6 +54,10 @@ type zip_library = { let whitelisted_cpp_methods = [ ["std"; "move"]; + ["std"; "forward"]; + ["std"; "min"]; + ["std"; "max"]; + ["std"; "__less"]; ["google"; "CheckNotNull"]; ["google"; "GetReferenceableValue"]; ["google"; "Check_NEImpl"]; diff --git a/infer/tests/codetoanalyze/cpp/errors/numeric/min_max.cpp b/infer/tests/codetoanalyze/cpp/errors/numeric/min_max.cpp new file mode 100644 index 000000000..6f757cb50 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/errors/numeric/min_max.cpp @@ -0,0 +1,50 @@ +/* + * 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 + +struct X { + X(int f) : f(f) {} + int f; +}; +bool operator<(const X& x1, const X& x2) { return x1.f < x2.f; } + +struct X_inv { + X_inv(int f) : f(f) {} + int f; +}; +bool operator<(const X_inv& x1, const X_inv& x2) { return x1.f > x2.f; } + +int min_int_div0() { return 1 / std::min(1, 0); } + +int min_int_div_1() { return 1 / std::min(-1, 0); } + +int max_int_div1() { return 1 / std::max(1, 0); } + +int max_int_div0() { return 1 / std::max(0, -1); } + +int min_X_div0() { + X x0(0), x1(1); + return 1 / std::min(x0, x1).f; +} + +int max_X_div1() { + X x0(0), x1(1); + return 1 / std::max(x0, x1).f; +} + +int min_X_inv_div1() { + X_inv x0(0), x1(1); + return 1 / std::min(x0, x1).f; +} + +int max_X_inv_div0() { + X_inv x0(0), x1(1); + return 1 / std::max(x0, x1).f; +} diff --git a/infer/tests/endtoend/cpp/MinMaxNumericTest.java b/infer/tests/endtoend/cpp/MinMaxNumericTest.java new file mode 100644 index 000000000..31129a98a --- /dev/null +++ b/infer/tests/endtoend/cpp/MinMaxNumericTest.java @@ -0,0 +1,66 @@ +/* + * 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 MinMaxNumericTest { + + public static final String FILE = + "infer/tests/codetoanalyze/cpp/errors/numeric/min_max.cpp"; + + private static ImmutableList inferCmd; + + public static final String DIVIDE_BY_ZERO = "DIVIDE_BY_ZERO"; + + @ClassRule + public static DebuggableTemporaryFolder folder = + new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createCPPInferCommand(folder, FILE); + } + + @Test + public void whenInferRunsOnDiv0MethodsErrorIsFound() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferCPP(inferCmd); + String[] procedures = { + "min_int_div0", + "max_int_div0", + "min_X_div0", + "max_X_inv_div0", + }; + assertThat( + "Results should contain the expected divide by zero", + inferResults, + containsExactly( + DIVIDE_BY_ZERO, + FILE, + procedures + ) + ); + } +}