aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2020-03-16 07:03:23 +0300
committerArtem Dergachev <artem.dergachev@gmail.com>2020-03-16 07:16:44 +0300
commit0eba5dc80fb0a65b8bad00998c390ce3ec0c430f (patch)
tree91d960df85a956688670da162059fa9990b1c2f5
parent54146cbd32e319029cd1ff8519f76e2a3820bb8c (diff)
[analyzer] Fix modeling some library functions when UCHAR_MAX > INT_MAX.
This makes life easier for downstream users who maintain exotic target platforms. Patch by Vince Bridgers! Differential Revision: https://reviews.llvm.org/D75529
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp42
1 files changed, 27 insertions, 15 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
index d52b3f371af9..6af63fc28e23 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -510,8 +510,14 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
const RangeInt LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue();
- const RangeInt UCharMax =
- BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue();
+ // Set UCharRangeMax to min of int or uchar maximum value.
+ // The C standard states that the arguments of functions like isalpha must
+ // be representable as an unsigned char. Their type is 'int', so the max
+ // value of the argument should be min(UCharMax, IntMax). This just happen
+ // to be true for commonly used and well tested instruction set
+ // architectures, but not for others.
+ const RangeInt UCharRangeMax =
+ std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax);
// The platform dependent value of EOF.
// Try our best to parse this from the Preprocessor, otherwise fallback to -1.
@@ -573,8 +579,8 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
// Templates for summaries that are reused by many functions.
auto Getc = [&]() {
return Summary(ArgTypes{Irrelevant}, RetType{IntTy}, NoEvalCall)
- .Case(
- {ReturnValueCondition(WithinRange, {{EOFv, EOFv}, {0, UCharMax}})});
+ .Case({ReturnValueCondition(WithinRange,
+ {{EOFv, EOFv}, {0, UCharRangeMax}})});
};
auto Read = [&](RetType R, RangeInt Max) {
return Summary(ArgTypes{Irrelevant, Irrelevant, SizeTy}, RetType{R},
@@ -609,12 +615,13 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
// The locale-specific range.
// No post-condition. We are completely unaware of
// locale-specific return values.
- .Case({ArgumentCondition(0U, WithinRange, {{128, UCharMax}})})
+ .Case({ArgumentCondition(0U, WithinRange,
+ {{128, UCharRangeMax}})})
.Case({ArgumentCondition(0U, OutOfRange,
{{'0', '9'},
{'A', 'Z'},
{'a', 'z'},
- {128, UCharMax}}),
+ {128, UCharRangeMax}}),
ReturnValueCondition(WithinRange, SingleValue(0))})},
},
{
@@ -625,10 +632,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
{{'A', 'Z'}, {'a', 'z'}}),
ReturnValueCondition(OutOfRange, SingleValue(0))})
// The locale-specific range.
- .Case({ArgumentCondition(0U, WithinRange, {{128, UCharMax}})})
+ .Case({ArgumentCondition(0U, WithinRange,
+ {{128, UCharRangeMax}})})
.Case({ArgumentCondition(
0U, OutOfRange,
- {{'A', 'Z'}, {'a', 'z'}, {128, UCharMax}}),
+ {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
ReturnValueCondition(WithinRange, SingleValue(0))})},
},
{
@@ -692,9 +700,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
ArgumentCondition(0U, OutOfRange, Range('a', 'z')),
ReturnValueCondition(WithinRange, SingleValue(0))})
// The locale-specific range.
- .Case({ArgumentCondition(0U, WithinRange, {{128, UCharMax}})})
+ .Case({ArgumentCondition(0U, WithinRange,
+ {{128, UCharRangeMax}})})
// Is not an unsigned char.
- .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharMax)),
+ .Case({ArgumentCondition(0U, OutOfRange,
+ Range(0, UCharRangeMax)),
ReturnValueCondition(WithinRange, SingleValue(0))})},
},
{
@@ -728,10 +738,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
{{9, 13}, {' ', ' '}}),
ReturnValueCondition(OutOfRange, SingleValue(0))})
// The locale-specific range.
- .Case({ArgumentCondition(0U, WithinRange, {{128, UCharMax}})})
+ .Case({ArgumentCondition(0U, WithinRange,
+ {{128, UCharRangeMax}})})
.Case({ArgumentCondition(
0U, OutOfRange,
- {{9, 13}, {' ', ' '}, {128, UCharMax}}),
+ {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}),
ReturnValueCondition(WithinRange, SingleValue(0))})},
},
{
@@ -742,10 +753,11 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
.Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')),
ReturnValueCondition(OutOfRange, SingleValue(0))})
// The locale-specific range.
- .Case({ArgumentCondition(0U, WithinRange, {{128, UCharMax}})})
+ .Case({ArgumentCondition(0U, WithinRange,
+ {{128, UCharRangeMax}})})
// Other.
.Case({ArgumentCondition(0U, OutOfRange,
- {{'A', 'Z'}, {128, UCharMax}}),
+ {{'A', 'Z'}, {128, UCharRangeMax}}),
ReturnValueCondition(WithinRange, SingleValue(0))})},
},
{
@@ -768,7 +780,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries(
{"getchar",
Summaries{Summary(ArgTypes{}, RetType{IntTy}, NoEvalCall)
.Case({ReturnValueCondition(
- WithinRange, {{EOFv, EOFv}, {0, UCharMax}})})}},
+ WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})})}},
// read()-like functions that never return more than buffer size.
// We are not sure how ssize_t is defined on every platform, so we