diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index a444843c50060..a61af45231348 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -349,7 +349,6 @@ let ParentPackage = APIModeling in { def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, HelpText<"Improve modeling of the C standard library functions">, - Dependencies<[CallAndMessageModeling]>, CheckerOptions<[ CmdLineOption, "such as whether the parameter of isalpha is in the range [0, 255] " "or is EOF.">, Dependencies<[StdCLibraryFunctionsChecker]>, - WeakDependencies<[NonNullParamChecker]>, + WeakDependencies<[CallAndMessageChecker, NonNullParamChecker, StreamChecker]>, Documentation; } // end "alpha.unix" diff --git a/clang/test/Analysis/analyzer-enabled-checkers.c b/clang/test/Analysis/analyzer-enabled-checkers.c index 7c00e78c16acd..bef786a1a59b6 100644 --- a/clang/test/Analysis/analyzer-enabled-checkers.c +++ b/clang/test/Analysis/analyzer-enabled-checkers.c @@ -6,11 +6,11 @@ // CHECK: OVERVIEW: Clang Static Analyzer Enabled Checkers List // CHECK-EMPTY: -// CHECK-NEXT: core.CallAndMessageModeling // CHECK-NEXT: apiModeling.StdCLibraryFunctions // CHECK-NEXT: apiModeling.TrustNonnull // CHECK-NEXT: apiModeling.llvm.CastValue // CHECK-NEXT: apiModeling.llvm.ReturnValue +// CHECK-NEXT: core.CallAndMessageModeling // CHECK-NEXT: core.CallAndMessage // CHECK-NEXT: core.DivideZero // CHECK-NEXT: core.DynamicTypePropagation diff --git a/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c new file mode 100644 index 0000000000000..9ad1be0538517 --- /dev/null +++ b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c @@ -0,0 +1,66 @@ +// Here we test the order of the Checkers when StdCLibraryFunctionArgs is +// enabled. + +// RUN: %clang --analyze %s --target=x86_64-pc-linux-gnu \ +// RUN: -Xclang -analyzer-checker=core \ +// RUN: -Xclang -analyzer-checker=apiModeling.StdCLibraryFunctions \ +// RUN: -Xclang -analyzer-config \ +// RUN: -Xclang apiModeling.StdCLibraryFunctions:ModelPOSIX=true \ +// RUN: -Xclang -analyzer-checker=alpha.unix.StdCLibraryFunctionArgs \ +// RUN: -Xclang -analyzer-checker=alpha.unix.Stream \ +// RUN: -Xclang -analyzer-list-enabled-checkers \ +// RUN: -Xclang -analyzer-display-progress \ +// RUN: 2>&1 | FileCheck %s --implicit-check-not=ANALYZE \ +// RUN: --implicit-check-not=\. + +// CHECK: OVERVIEW: Clang Static Analyzer Enabled Checkers List +// CHECK-EMPTY: +// CHECK-NEXT: core.CallAndMessageModeling +// CHECK-NEXT: core.CallAndMessage +// CHECK-NEXT: core.NonNullParamChecker +// CHECK-NEXT: alpha.unix.Stream +// CHECK-NEXT: apiModeling.StdCLibraryFunctions +// CHECK-NEXT: alpha.unix.StdCLibraryFunctionArgs +// CHECK-NEXT: apiModeling.TrustNonnull +// CHECK-NEXT: apiModeling.llvm.CastValue +// CHECK-NEXT: apiModeling.llvm.ReturnValue +// CHECK-NEXT: core.DivideZero +// CHECK-NEXT: core.DynamicTypePropagation +// CHECK-NEXT: core.NonnilStringConstants +// CHECK-NEXT: core.NullDereference +// CHECK-NEXT: core.StackAddrEscapeBase +// CHECK-NEXT: core.StackAddressEscape +// CHECK-NEXT: core.UndefinedBinaryOperatorResult +// CHECK-NEXT: core.VLASize +// CHECK-NEXT: core.builtin.BuiltinFunctions +// CHECK-NEXT: core.builtin.NoReturnFunctions +// CHECK-NEXT: core.uninitialized.ArraySubscript +// CHECK-NEXT: core.uninitialized.Assign +// CHECK-NEXT: core.uninitialized.Branch +// CHECK-NEXT: core.uninitialized.CapturedBlockVariable +// CHECK-NEXT: core.uninitialized.UndefReturn +// CHECK-NEXT: deadcode.DeadStores +// CHECK-NEXT: nullability.NullabilityBase +// CHECK-NEXT: nullability.NullPassedToNonnull +// CHECK-NEXT: nullability.NullReturnedFromNonnull +// CHECK-NEXT: security.insecureAPI.SecuritySyntaxChecker +// CHECK-NEXT: security.insecureAPI.UncheckedReturn +// CHECK-NEXT: security.insecureAPI.getpw +// CHECK-NEXT: security.insecureAPI.gets +// CHECK-NEXT: security.insecureAPI.mkstemp +// CHECK-NEXT: security.insecureAPI.mktemp +// CHECK-NEXT: security.insecureAPI.vfork +// CHECK-NEXT: unix.API +// CHECK-NEXT: unix.cstring.CStringModeling +// CHECK-NEXT: unix.DynamicMemoryModeling +// CHECK-NEXT: unix.Malloc +// CHECK-NEXT: unix.MallocSizeof +// CHECK-NEXT: unix.MismatchedDeallocator +// CHECK-NEXT: unix.Vfork +// CHECK-NEXT: unix.cstring.BadSizeArg +// CHECK-NEXT: unix.cstring.NullArg + +int main() { + int i; + (void)(10 / i); +} diff --git a/clang/test/Analysis/std-c-library-functions-arg-weakdeps.c b/clang/test/Analysis/std-c-library-functions-arg-weakdeps.c new file mode 100644 index 0000000000000..0ad3c277dfd7d --- /dev/null +++ b/clang/test/Analysis/std-c-library-functions-arg-weakdeps.c @@ -0,0 +1,64 @@ +// Check that the more specific checkers report and not the generic +// StdCLibraryFunctionArgs checker. + +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \ +// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true \ +// RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctionArgs \ +// RUN: -analyzer-checker=alpha.unix.Stream \ +// RUN: -triple x86_64-unknown-linux-gnu \ +// RUN: -verify + + +// Make sure that all used functions have their summary loaded. + +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \ +// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true \ +// RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctionArgs \ +// RUN: -analyzer-checker=alpha.unix.Stream \ +// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:DisplayLoadedSummaries=true \ +// RUN: -triple x86_64-unknown-linux 2>&1 | FileCheck %s + +// CHECK: Loaded summary for: int isalnum(int) +// CHECK: Loaded summary for: unsigned long fread(void *restrict, size_t, size_t, FILE *restrict) __attribute__((nonnull(1))) +// CHECK: Loaded summary for: int fileno(FILE *stream) + +void initializeSummaryMap(); +// We analyze this function first, and the call expression inside initializes +// the summary map. This way we force the loading of the summaries. The +// summaries would not be loaded without this because during the first bug +// report in WeakDependency::checkPreCall we stop further evaluation. And +// StdLibraryFunctionsChecker lazily initializes its summary map from its +// checkPreCall. +void analyzeThisFirst() { + initializeSummaryMap(); +} + +typedef __typeof(sizeof(int)) size_t; +struct FILE; +typedef struct FILE FILE; + +int isalnum(int); +size_t fread(void *restrict, size_t, size_t, FILE *restrict) __attribute__((nonnull(1))); +int fileno(FILE *stream); + +void test_uninit_arg() { + int v; + int r = isalnum(v); // \ + // expected-warning{{1st function call argument is an uninitialized value [core.CallAndMessage]}} + (void)r; +} + +void test_notnull_arg(FILE *F) { + int *p = 0; + fread(p, sizeof(int), 5, F); // \ + expected-warning{{Null pointer passed to 1st parameter expecting 'nonnull' [core.NonNullParamChecker]}} +} + +void test_notnull_stream_arg() { + fileno(0); // \ + // expected-warning{{Stream pointer might be NULL [alpha.unix.Stream]}} +}