Skip to content

Commit 4f0436d

Browse files
committed
[clang][analyzer] Merge apiModeling.StdCLibraryFunctions and StdCLibraryFunctionArgs checkers into one.
Main reason for this change is that these checkers were implemented in the same class but had different dependency ordering. (NonNullParamChecker should run before StdCLibraryFunctionArgs to get more special warning about null arguments, but the apiModeling.StdCLibraryFunctions was a modeling checker that should run before other non-modeling checkers. The modeling checker changes state in a way that makes it impossible to detect a null argument by NonNullParamChecker.) To make it more simple, the modeling part is removed as separate checker and can be only used if checker StdCLibraryFunctions is turned on, that produces the warnings too. Modeling the functions without bug detection (for invalid argument) is not possible. The modeling of standard functions does not happen by default from this change on. Reviewed By: Szelethus Differential Revision: https://reviews.llvm.org/D151225
1 parent dfb3693 commit 4f0436d

37 files changed

+146
-179
lines changed

clang/docs/analyzer/checkers.rst

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,10 +2421,10 @@ For a more detailed description of configuration options, please see the :doc:`u
24212421
alpha.unix
24222422
^^^^^^^^^^^
24232423
2424-
.. _alpha-unix-StdCLibraryFunctionArgs:
2424+
.. _alpha-unix-StdCLibraryFunctions:
24252425
2426-
alpha.unix.StdCLibraryFunctionArgs (C)
2427-
""""""""""""""""""""""""""""""""""""""
2426+
alpha.unix.StdCLibraryFunctions (C)
2427+
"""""""""""""""""""""""""""""""""""
24282428
Check for calls of standard library functions that violate predefined argument
24292429
constraints. For example, it is stated in the C standard that for the ``int
24302430
isalnum(int ch)`` function the behavior is undefined if the value of ``ch`` is
@@ -2457,6 +2457,12 @@ on standard library functions. Preconditions are checked, and when they are
24572457
violated, a warning is emitted. Post conditions are added to the analysis, e.g.
24582458
that the return value must be no greater than 255.
24592459
2460+
For example if an argument to a function must be in between 0 and 255, but the
2461+
value of the argument is unknown, the analyzer will conservatively assume that
2462+
it is in this interval. Similarly, if a function mustn't be called with a null
2463+
pointer and the null value of the argument can not be proven, the analyzer will
2464+
assume that it is non-null.
2465+
24602466
These are the possible checks on the values passed as function arguments:
24612467
- The argument has an allowed range (or multiple ranges) of values. The checker
24622468
can detect if a passed value is outside of the allowed range and show the
@@ -2471,16 +2477,6 @@ These are the possible checks on the values passed as function arguments:
24712477
checker can detect if the buffer size is too small and in optimal case show
24722478
the size of the buffer and the values of the corresponding arguments.
24732479
2474-
If the user disables the checker then the argument violation warning is
2475-
suppressed. However, the assumption about the argument is still modeled.
2476-
For instance, if the argument to a function must be in between 0 and 255,
2477-
but the value of the argument is unknown, the analyzer will conservatively
2478-
assume that it is in this interval, even if warnings for this checker are
2479-
disabled. Similarly, if a function mustn't be called with a null pointer but it
2480-
is, analysis will stop on that execution path (similarly to a division by zero),
2481-
with or without a warning. If the null value of the argument can not be proven,
2482-
the analyzer will assume that it is non-null.
2483-
24842480
.. code-block:: c
24852481
24862482
int test_alnum_symbolic(int x) {
@@ -2493,6 +2489,13 @@ the analyzer will assume that it is non-null.
24932489
return ret;
24942490
}
24952491
2492+
Additionally to the argument and return value conditions, this checker also adds
2493+
state of the value ``errno`` if applicable to the analysis. Many system
2494+
functions set the ``errno`` value only if an error occurs (together with a
2495+
specific return value of the function), otherwise it becomes undefined. This
2496+
checker changes the analysis state to contain such information. This data is
2497+
used by other checkers, for example :ref:`alpha-unix-Errno`.
2498+
24962499
**Limitations**
24972500
24982501
The checker can not always provide notes about the values of the arguments.
@@ -2508,12 +2511,9 @@ range of the argument.
25082511
**Parameters**
25092512
25102513
The checker models functions (and emits diagnostics) from the C standard by
2511-
default. The ``apiModeling.StdCLibraryFunctions:ModelPOSIX`` option enables
2512-
modeling (and emit diagnostics) of additional functions that are defined in the
2513-
POSIX standard. This option is disabled by default. Note that this option
2514-
belongs to a separate built-in checker ``apiModeling.StdCLibraryFunctions`` and
2515-
can have effect on other checkers because it toggles modeling of the functions
2516-
in various aspects.
2514+
default. The ``ModelPOSIX`` option enables modeling (and emit diagnostics) of
2515+
additional functions that are defined in the POSIX standard. This option is
2516+
disabled by default.
25172517
25182518
.. _alpha-unix-BlockInCriticalSection:
25192519
@@ -2582,9 +2582,10 @@ pages of the functions and in the `POSIX standard <https://pubs.opengroup.org/on
25822582
return 1;
25832583
}
25842584
2585-
The supported functions are the same that are modeled by checker
2586-
:ref:`alpha-unix-StdCLibraryFunctionArgs`.
2587-
The ``ModelPOSIX`` option of that checker affects the set of checked functions.
2585+
The checker :ref:`alpha-unix-StdCLibraryFunctions` must be turned on to get the
2586+
warnings from this checker. The supported functions are the same as by
2587+
:ref:`alpha-unix-StdCLibraryFunctions`. The ``ModelPOSIX`` option of that
2588+
checker affects the set of checked functions.
25882589
25892590
**Parameters**
25902591

clang/include/clang/StaticAnalyzer/Checkers/Checkers.td

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -359,29 +359,6 @@ def ErrnoModeling : Checker<"Errno">,
359359
HelpText<"Make the special value 'errno' available to other checkers.">,
360360
Documentation<NotDocumented>;
361361

362-
def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
363-
HelpText<"Improve modeling of the C standard library functions">,
364-
// Uninitialized value check is a mandatory dependency. This Checker asserts
365-
// that arguments are always initialized.
366-
Dependencies<[CallAndMessageModeling]>,
367-
CheckerOptions<[
368-
CmdLineOption<Boolean,
369-
"DisplayLoadedSummaries",
370-
"If set to true, the checker displays the found summaries "
371-
"for the given translation unit.",
372-
"false",
373-
Released,
374-
Hide>,
375-
CmdLineOption<Boolean,
376-
"ModelPOSIX",
377-
"If set to true, the checker models functions from the "
378-
"POSIX standard.",
379-
"false",
380-
InAlpha>
381-
]>,
382-
Documentation<NotDocumented>,
383-
Hidden;
384-
385362
def TrustNonnullChecker : Checker<"TrustNonnull">,
386363
HelpText<"Trust that returns from framework methods annotated with _Nonnull "
387364
"are not null">,
@@ -583,11 +560,24 @@ def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
583560
HelpText<"Check for calls to blocking functions inside a critical section">,
584561
Documentation<HasDocumentation>;
585562

586-
def StdCLibraryFunctionArgsChecker : Checker<"StdCLibraryFunctionArgs">,
587-
HelpText<"Check constraints of arguments of C standard library functions, "
588-
"such as whether the parameter of isalpha is in the range [0, 255] "
589-
"or is EOF.">,
590-
Dependencies<[StdCLibraryFunctionsChecker]>,
563+
def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
564+
HelpText<"Check for invalid arguments of C standard library functions, "
565+
"and apply relations between arguments and return value">,
566+
CheckerOptions<[
567+
CmdLineOption<Boolean,
568+
"DisplayLoadedSummaries",
569+
"If set to true, the checker displays the found summaries "
570+
"for the given translation unit.",
571+
"false",
572+
Released,
573+
Hide>,
574+
CmdLineOption<Boolean,
575+
"ModelPOSIX",
576+
"If set to true, the checker models additional functions "
577+
"from the POSIX standard.",
578+
"false",
579+
InAlpha>
580+
]>,
591581
WeakDependencies<[CallAndMessageChecker, NonNullParamChecker]>,
592582
Documentation<HasDocumentation>;
593583

@@ -1618,7 +1608,6 @@ def DebugIteratorModeling : Checker<"DebugIteratorModeling">,
16181608
def StdCLibraryFunctionsTesterChecker : Checker<"StdCLibraryFunctionsTester">,
16191609
HelpText<"Add test functions to the summary map, so testing of individual "
16201610
"summary constituents becomes possible.">,
1621-
Dependencies<[StdCLibraryFunctionsChecker]>,
16221611
Documentation<NotDocumented>;
16231612

16241613
} // end "debug"

clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -790,13 +790,8 @@ class StdLibraryFunctionsChecker
790790
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
791791
bool evalCall(const CallEvent &Call, CheckerContext &C) const;
792792

793-
enum CheckKind {
794-
CK_StdCLibraryFunctionArgsChecker,
795-
CK_StdCLibraryFunctionsTesterChecker,
796-
CK_NumCheckKinds
797-
};
798-
bool ChecksEnabled[CK_NumCheckKinds] = {false};
799-
CheckerNameRef CheckNames[CK_NumCheckKinds];
793+
CheckerNameRef CheckName;
794+
bool AddTestFunctions = false;
800795

801796
bool DisplayLoadedSummaries = false;
802797
bool ModelPOSIX = false;
@@ -813,8 +808,6 @@ class StdLibraryFunctionsChecker
813808
void reportBug(const CallEvent &Call, ExplodedNode *N,
814809
const ValueConstraint *VC, const ValueConstraint *NegatedVC,
815810
const Summary &Summary, CheckerContext &C) const {
816-
if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker])
817-
return;
818811
assert(Call.getDecl() &&
819812
"Function found in summary must have a declaration available");
820813
SmallString<256> Msg;
@@ -834,8 +827,8 @@ class StdLibraryFunctionsChecker
834827
Msg[0] = toupper(Msg[0]);
835828
if (!BT_InvalidArg)
836829
BT_InvalidArg = std::make_unique<BugType>(
837-
CheckNames[CK_StdCLibraryFunctionArgsChecker],
838-
"Function call with invalid argument", categories::LogicError);
830+
CheckName, "Function call with invalid argument",
831+
categories::LogicError);
839832
auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N);
840833

841834
for (ArgNo ArgN : VC->getArgsToTrack()) {
@@ -1423,6 +1416,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
14231416
CheckerContext &C) const {
14241417
if (SummariesInitialized)
14251418
return;
1419+
SummariesInitialized = true;
14261420

14271421
SValBuilder &SVB = C.getSValBuilder();
14281422
BasicValueFactory &BVF = SVB.getBasicValueFactory();
@@ -3370,7 +3364,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
33703364
}
33713365

33723366
// Functions for testing.
3373-
if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) {
3367+
if (AddTestFunctions) {
33743368
const RangeInt IntMin = BVF.getMinValue(IntTy).getLimitedValue();
33753369

33763370
addToFunctionSummaryMap(
@@ -3594,12 +3588,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
35943588
ReturnValueCondition(WithinRange, SingleValue(4))},
35953589
ErrnoIrrelevant));
35963590
}
3597-
3598-
SummariesInitialized = true;
35993591
}
36003592

36013593
void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
36023594
auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>();
3595+
Checker->CheckName = mgr.getCurrentCheckerName();
36033596
const AnalyzerOptions &Opts = mgr.getAnalyzerOptions();
36043597
Checker->DisplayLoadedSummaries =
36053598
Opts.getCheckerBooleanOption(Checker, "DisplayLoadedSummaries");
@@ -3613,16 +3606,12 @@ bool ento::shouldRegisterStdCLibraryFunctionsChecker(
36133606
return true;
36143607
}
36153608

3616-
#define REGISTER_CHECKER(name) \
3617-
void ento::register##name(CheckerManager &mgr) { \
3618-
StdLibraryFunctionsChecker *checker = \
3619-
mgr.getChecker<StdLibraryFunctionsChecker>(); \
3620-
checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true; \
3621-
checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] = \
3622-
mgr.getCurrentCheckerName(); \
3623-
} \
3624-
\
3625-
bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
3626-
3627-
REGISTER_CHECKER(StdCLibraryFunctionArgsChecker)
3628-
REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker)
3609+
void ento::registerStdCLibraryFunctionsTesterChecker(CheckerManager &mgr) {
3610+
auto *Checker = mgr.getChecker<StdLibraryFunctionsChecker>();
3611+
Checker->AddTestFunctions = true;
3612+
}
3613+
3614+
bool ento::shouldRegisterStdCLibraryFunctionsTesterChecker(
3615+
const CheckerManager &mgr) {
3616+
return true;
3617+
}

clang/test/Analysis/PR49642.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %clang_analyze_cc1 -Wno-implicit-function-declaration -Wno-implicit-int -w -verify %s \
22
// RUN: -analyzer-checker=core \
3-
// RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions
3+
// RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctions
44

55
// expected-no-diagnostics
66

clang/test/Analysis/analyzer-config.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
// CHECK-NEXT: alpha.security.MmapWriteExec:MmapProtRead = 0x01
1414
// CHECK-NEXT: alpha.security.taint.TaintPropagation:Config = ""
1515
// CHECK-NEXT: alpha.unix.Errno:AllowErrnoReadOutsideConditionExpressions = true
16-
// CHECK-NEXT: apiModeling.StdCLibraryFunctions:DisplayLoadedSummaries = false
17-
// CHECK-NEXT: apiModeling.StdCLibraryFunctions:ModelPOSIX = false
16+
// CHECK-NEXT: alpha.unix.StdCLibraryFunctions:DisplayLoadedSummaries = false
17+
// CHECK-NEXT: alpha.unix.StdCLibraryFunctions:ModelPOSIX = false
1818
// CHECK-NEXT: apply-fixits = false
1919
// CHECK-NEXT: assume-controlled-environment = false
2020
// CHECK-NEXT: avoid-suppressing-null-argument-paths = false

clang/test/Analysis/analyzer-enabled-checkers.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@
77
// CHECK: OVERVIEW: Clang Static Analyzer Enabled Checkers List
88
// CHECK-EMPTY:
99
// CHECK-NEXT: apiModeling.Errno
10-
// CHECK-NEXT: core.CallAndMessageModeling
11-
// CHECK-NEXT: apiModeling.StdCLibraryFunctions
1210
// CHECK-NEXT: apiModeling.TrustNonnull
1311
// CHECK-NEXT: apiModeling.TrustReturnsNonnull
1412
// CHECK-NEXT: apiModeling.llvm.CastValue
1513
// CHECK-NEXT: apiModeling.llvm.ReturnValue
14+
// CHECK-NEXT: core.CallAndMessageModeling
1615
// CHECK-NEXT: core.CallAndMessage
1716
// CHECK-NEXT: core.DivideZero
1817
// CHECK-NEXT: core.DynamicTypePropagation

clang/test/Analysis/conversion.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %clang_analyze_cc1 %s \
22
// RUN: -Wno-conversion -Wno-tautological-constant-compare \
3-
// RUN: -analyzer-checker=core,apiModeling,alpha.core.Conversion \
3+
// RUN: -analyzer-checker=core,apiModeling,alpha.unix.StdCLibraryFunctions,alpha.core.Conversion \
44
// RUN: -verify
55

66
unsigned char U8;
@@ -187,7 +187,7 @@ char dontwarn10(long long x) {
187187
}
188188

189189

190-
// C library functions, handled via apiModeling.StdCLibraryFunctions
190+
// C library functions, handled via alpha.unix.StdCLibraryFunctions
191191

192192
int isascii(int c);
193193
void libraryFunction1(void) {

clang/test/Analysis/errno-stdlibraryfunctions-notes.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// RUN: %clang_analyze_cc1 -verify -analyzer-output text %s \
22
// RUN: -analyzer-checker=core \
33
// RUN: -analyzer-checker=debug.ExprInspection \
4-
// RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \
4+
// RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctions \
55
// RUN: -analyzer-checker=apiModeling.Errno \
66
// RUN: -analyzer-checker=alpha.unix.Errno \
7-
// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true
7+
// RUN: -analyzer-config alpha.unix.StdCLibraryFunctions:ModelPOSIX=true
88

99
#include "Inputs/errno_var.h"
1010

clang/test/Analysis/errno-stdlibraryfunctions.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// RUN: %clang_analyze_cc1 -verify %s \
22
// RUN: -analyzer-checker=core \
33
// RUN: -analyzer-checker=debug.ExprInspection \
4-
// RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \
4+
// RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctions \
55
// RUN: -analyzer-checker=apiModeling.Errno \
66
// RUN: -analyzer-checker=alpha.unix.Errno \
7-
// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true
7+
// RUN: -analyzer-config alpha.unix.StdCLibraryFunctions:ModelPOSIX=true
88

99
#include "Inputs/errno_var.h"
1010

clang/test/Analysis/std-c-library-functions-POSIX-lookup.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %clang_analyze_cc1 %s \
22
// RUN: -analyzer-checker=core \
3-
// RUN: -analyzer-checker=apiModeling.StdCLibraryFunctions \
4-
// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true \
5-
// RUN: -analyzer-config apiModeling.StdCLibraryFunctions:DisplayLoadedSummaries=true \
3+
// RUN: -analyzer-checker=alpha.unix.StdCLibraryFunctions \
4+
// RUN: -analyzer-config alpha.unix.StdCLibraryFunctions:ModelPOSIX=true \
5+
// RUN: -analyzer-config alpha.unix.StdCLibraryFunctions:DisplayLoadedSummaries=true \
66
// RUN: -analyzer-checker=debug.ExprInspection \
77
// RUN: -analyzer-config eagerly-assume=false \
88
// RUN: -triple i686-unknown-linux 2>&1 | FileCheck %s --allow-empty

0 commit comments

Comments
 (0)