//
// The following standard C functions are currently supported:
//
-// fgetc getline isdigit isupper
+// fgetc getline isdigit isupper toascii
// fread isalnum isgraph isxdigit
// fwrite isalpha islower read
// getc isascii isprint write
-// getchar isblank ispunct
-// getdelim iscntrl isspace
+// getchar isblank ispunct toupper
+// getdelim iscntrl isspace tolower
//
//===----------------------------------------------------------------------===//
RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Args)
: ValueConstraint(ArgN), Kind(Kind), Args(Args) {}
- const IntRangeVector &getRanges() const {
- return Args;
- }
+ const IntRangeVector &getRanges() const { return Args; }
private:
ProgramStateRef applyAsOutOfRange(ProgramStateRef State,
ProgramStateRef applyAsWithinRange(ProgramStateRef State,
const CallEvent &Call,
const Summary &Summary) const;
+
public:
ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
const Summary &Summary,
return *this;
}
- Summary &Case(ConstraintSet&& CS) {
+ Summary &Case(ConstraintSet &&CS) {
CaseConstraints.push_back(std::move(CS));
return *this;
}
const QualType LongLongTy = ACtx.LongLongTy;
const QualType SizeTy = ACtx.getSizeType();
- const QualType VoidPtrTy = ACtx.VoidPtrTy; // void *
+ const QualType VoidPtrTy = ACtx.VoidPtrTy; // void *
const QualType IntPtrTy = ACtx.getPointerType(IntTy); // int *
const QualType UnsignedIntPtrTy =
ACtx.getPointerType(UnsignedIntTy); // unsigned int *
const QualType VoidPtrRestrictTy = getRestrictTy(VoidPtrTy);
const QualType ConstVoidPtrTy =
- ACtx.getPointerType(ACtx.VoidTy.withConst()); // const void *
+ ACtx.getPointerType(ACtx.VoidTy.withConst()); // const void *
const QualType CharPtrTy = ACtx.getPointerType(ACtx.CharTy); // char *
const QualType CharPtrRestrictTy = getRestrictTy(CharPtrTy);
const QualType ConstCharPtrTy =
.Case({ArgumentCondition(0U, OutOfRange,
{{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
ReturnValueCondition(WithinRange, SingleValue(0))}));
+ addToFunctionSummaryMap(
+ "toupper", Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(
+ 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
+ addToFunctionSummaryMap(
+ "tolower", Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(
+ 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
+ addToFunctionSummaryMap(
+ "toascii", Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure)
+ .ArgConstraint(ArgumentCondition(
+ 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
// The getc() family of functions that returns either a char or an EOF.
if (FilePtrTy) {
mgr.getAnalyzerOptions().getCheckerBooleanOption(Checker, "ModelPOSIX");
}
-bool ento::shouldRegisterStdCLibraryFunctionsChecker(const CheckerManager &mgr) {
+bool ento::shouldRegisterStdCLibraryFunctionsChecker(
+ const CheckerManager &mgr) {
return true;
}
// bugpath-note{{TRUE}} \
// bugpath-note{{Left side of '&&' is true}} \
// bugpath-note{{'x' is <= 255}}
-
}
void test_alnum_symbolic2(int x) {
}
}
+int toupper(int);
+
+void test_toupper_concrete(int v) {
+ int ret = toupper(256); // \
+ // report-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-note{{Function argument constraint is not satisfied}}
+ (void)ret;
+}
+
+void test_toupper_symbolic(int x) {
+ int ret = toupper(x);
+ (void)ret;
+
+ clang_analyzer_eval(EOF <= x && x <= 255); // \
+ // report-warning{{TRUE}} \
+ // bugpath-warning{{TRUE}} \
+ // bugpath-note{{TRUE}} \
+ // bugpath-note{{Left side of '&&' is true}} \
+ // bugpath-note{{'x' is <= 255}}
+}
+
+void test_toupper_symbolic2(int x) {
+ if (x > 255) { // \
+ // bugpath-note{{Assuming 'x' is > 255}} \
+ // bugpath-note{{Taking true branch}}
+
+ int ret = toupper(x); // \
+ // report-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-note{{Function argument constraint is not satisfied}}
+
+ (void)ret;
+ }
+}
+
+int tolower(int);
+
+void test_tolower_concrete(int v) {
+ int ret = tolower(256); // \
+ // report-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-note{{Function argument constraint is not satisfied}}
+ (void)ret;
+}
+
+void test_tolower_symbolic(int x) {
+ int ret = tolower(x);
+ (void)ret;
+
+ clang_analyzer_eval(EOF <= x && x <= 255); // \
+ // report-warning{{TRUE}} \
+ // bugpath-warning{{TRUE}} \
+ // bugpath-note{{TRUE}} \
+ // bugpath-note{{Left side of '&&' is true}} \
+ // bugpath-note{{'x' is <= 255}}
+}
+
+void test_tolower_symbolic2(int x) {
+ if (x > 255) { // \
+ // bugpath-note{{Assuming 'x' is > 255}} \
+ // bugpath-note{{Taking true branch}}
+
+ int ret = tolower(x); // \
+ // report-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-note{{Function argument constraint is not satisfied}}
+
+ (void)ret;
+ }
+}
+
+int toascii(int);
+
+void test_toascii_concrete(int v) {
+ int ret = toascii(256); // \
+ // report-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-note{{Function argument constraint is not satisfied}}
+ (void)ret;
+}
+
+void test_toascii_symbolic(int x) {
+ int ret = toascii(x);
+ (void)ret;
+
+ clang_analyzer_eval(EOF <= x && x <= 255); // \
+ // report-warning{{TRUE}} \
+ // bugpath-warning{{TRUE}} \
+ // bugpath-note{{TRUE}} \
+ // bugpath-note{{Left side of '&&' is true}} \
+ // bugpath-note{{'x' is <= 255}}
+}
+
+void test_toascii_symbolic2(int x) {
+ if (x > 255) { // \
+ // bugpath-note{{Assuming 'x' is > 255}} \
+ // bugpath-note{{Taking true branch}}
+
+ int ret = toascii(x); // \
+ // report-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-warning{{Function argument constraint is not satisfied}} \
+ // bugpath-note{{Function argument constraint is not satisfied}}
+
+ (void)ret;
+ }
+}
+
typedef struct FILE FILE;
typedef typeof(sizeof(int)) size_t;
size_t fread(void *restrict, size_t, size_t, FILE *restrict);
// bugpath-note{{'buf' is not equal to null}}
}
void test_notnull_symbolic2(FILE *fp, int *buf) {
- if (!buf) // bugpath-note{{Assuming 'buf' is null}} \
+ if (!buf) // bugpath-note{{Assuming 'buf' is null}} \
// bugpath-note{{Taking true branch}}
fread(buf, sizeof(int), 10, fp); // \
// report-warning{{Function argument constraint is not satisfied}} \
}
int __buf_size_arg_constraint_mul(const void *, size_t, size_t);
void test_buf_size_concrete_with_multiplication() {
- short buf[3]; // bugpath-note{{'buf' initialized here}}
+ short buf[3]; // bugpath-note{{'buf' initialized here}}
__buf_size_arg_constraint_mul(buf, 4, sizeof(short)); // \
// report-warning{{Function argument constraint is not satisfied}} \
// bugpath-warning{{Function argument constraint is not satisfied}} \