martong created this revision.
martong added reviewers: Szelethus, gamesh411, balazske.
Herald added subscribers: cfe-commits, ASDenysPetrov, steakhal, Charusso,
dkrupp, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet,
baloghadamsoftware, xazax.hun, whisperity.
Herald added a project: clang.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D84248
Files:
clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
clang/test/Analysis/std-c-library-functions-POSIX.c
Index: clang/test/Analysis/std-c-library-functions-POSIX.c
===================================================================
--- clang/test/Analysis/std-c-library-functions-POSIX.c
+++ clang/test/Analysis/std-c-library-functions-POSIX.c
@@ -95,6 +95,19 @@
// CHECK: Loaded summary for: ssize_t send(int sockfd, const void *buf, size_t len, int flags)
// CHECK: Loaded summary for: int socketpair(int domain, int type, int protocol, int sv[2])
// CHECK: Loaded summary for: int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, char *restrict node, socklen_t nodelen, char *restrict service, socklen_t servicelen, int flags)
+// CHECK: Loaded summary for: int utime(const char *filename, struct utimbuf *buf)
+// CHECK: Loaded summary for: int futimens(int fd, const struct timespec times[2])
+// CHECK: Loaded summary for: int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags)
+// CHECK: Loaded summary for: int utimes(const char *filename, const struct timeval times[2])
+// CHECK: Loaded summary for: int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
+// CHECK: Loaded summary for: struct tm *localtime(const time_t *tp)
+// CHECK: Loaded summary for: struct tm *localtime_r(const time_t *restrict timer, struct tm *restrict result)
+// CHECK: Loaded summary for: char *asctime_r(const struct tm *restrict tm, char *restrict buf)
+// CHECK: Loaded summary for: char *ctime_r(const time_t *timep, char *buf)
+// CHECK: Loaded summary for: struct tm *gmtime_r(const time_t *restrict timer, struct tm *restrict result)
+// CHECK: Loaded summary for: struct tm *gmtime(const time_t *tp)
+// CHECK: Loaded summary for: int clock_gettime(clockid_t clock_id, struct timespec *tp)
+// CHECK: Loaded summary for: int getitimer(int which, struct itimerval *curr_value)
long a64l(const char *str64);
char *l64a(long value);
@@ -226,6 +239,25 @@
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
int socketpair(int domain, int type, int protocol, int sv[2]);
int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, char *restrict node, socklen_t nodelen, char *restrict service, socklen_t servicelen, int flags);
+struct utimbuf;
+struct timespec { int x; };
+struct timeval { int x; };
+int utime(const char *filename, struct utimbuf *buf);
+int futimens(int fd, const struct timespec times[2]);
+int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags);
+int utimes(const char *filename, const struct timeval times[2]);
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+typedef unsigned long time_t;
+struct tm *localtime(const time_t *tp);
+struct tm *localtime_r(const time_t *restrict timer, struct tm *restrict result);
+char *asctime_r(const struct tm *restrict tm, char *restrict buf);
+char *ctime_r(const time_t *timep, char *buf);
+struct tm *gmtime_r(const time_t *restrict timer, struct tm *restrict result);
+struct tm *gmtime(const time_t *tp);
+typedef unsigned long clockid_t;
+int clock_gettime(clockid_t clock_id, struct timespec *tp);
+struct itimerval;
+int getitimer(int which, struct itimerval *curr_value);
// Must have at least one call expression to initialize the summary map.
int bar(void);
Index: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -1986,6 +1986,156 @@
BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5)))
.ArgConstraint(
ArgumentCondition(5, WithinRange, Range(0, *Socklen_tMax))));
+
+ Optional<QualType> StructUtimbufTy = lookupType("utimbuf", ACtx);
+ Optional<QualType> StructUtimbufPtrTy;
+ if (StructUtimbufTy)
+ StructUtimbufPtrTy = ACtx.getPointerType(*StructUtimbufTy);
+
+ if (StructUtimbufPtrTy)
+ // int utime(const char *filename, struct utimbuf *buf);
+ addToFunctionSummaryMap(
+ "utime", Summary(ArgTypes{ConstCharPtrTy, *StructUtimbufPtrTy},
+ RetType{IntTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0))));
+
+ Optional<QualType> StructTimespecTy = lookupType("timespec", ACtx);
+ Optional<QualType> StructTimespecPtrTy, ConstStructTimespecPtrTy;
+ if (StructTimespecTy) {
+ StructTimespecPtrTy = ACtx.getPointerType(*StructTimespecTy);
+ ConstStructTimespecPtrTy =
+ ACtx.getPointerType(StructTimespecTy->withConst());
+ }
+
+ if (ConstStructTimespecPtrTy) {
+ // int futimens(int fd, const struct timespec times[2]);
+ addToFunctionSummaryMap(
+ "futimens", Summary(ArgTypes{IntTy, *ConstStructTimespecPtrTy},
+ RetType{IntTy}, NoEvalCall)
+ .ArgConstraint(ArgumentCondition(0, WithinRange,
+ Range(0, IntMax))));
+
+ // int utimensat(int dirfd, const char *pathname,
+ // const struct timespec times[2], int flags);
+ addToFunctionSummaryMap(
+ "utimensat", Summary(ArgTypes{IntTy, ConstCharPtrTy,
+ *ConstStructTimespecPtrTy, IntTy},
+ RetType{IntTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(1))));
+ }
+
+ Optional<QualType> StructTimevalTy = lookupType("timeval", ACtx);
+ Optional<QualType> ConstStructTimevalPtrTy;
+ if (StructTimevalTy)
+ ConstStructTimevalPtrTy =
+ ACtx.getPointerType(StructTimevalTy->withConst());
+
+ if (ConstStructTimevalPtrTy)
+ // int utimes(const char *filename, const struct timeval times[2]);
+ addToFunctionSummaryMap(
+ "utimes", Summary(ArgTypes{ConstCharPtrTy, *ConstStructTimevalPtrTy},
+ RetType{IntTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0))));
+
+ if (ConstStructTimevalPtrTy && StructTimespecPtrTy)
+ // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+ addToFunctionSummaryMap(
+ "nanosleep",
+ Summary(ArgTypes{*ConstStructTimespecPtrTy, *StructTimespecPtrTy},
+ RetType{IntTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0))));
+
+ Optional<QualType> Time_tTy = lookupType("time_t", ACtx);
+ Optional<QualType> Time_tPtrTy, Time_tPtrRestrictTy, ConstTime_tPtrTy,
+ ConstTime_tPtrRestrictTy;
+ if (Time_tTy) {
+ Time_tPtrTy = ACtx.getPointerType(*Time_tTy);
+ Time_tPtrRestrictTy = getRestrictTy(*Time_tPtrTy);
+ ConstTime_tPtrTy = ACtx.getPointerType(Time_tTy->withConst());
+ ConstTime_tPtrRestrictTy = getRestrictTy(*ConstTime_tPtrTy);
+ }
+
+ Optional<QualType> StructTmTy = lookupType("tm", ACtx);
+ Optional<QualType> StructTmPtrTy, StructTmPtrRestrictTy, ConstStructTmPtrTy,
+ ConstStructTmPtrRestrictTy;
+ if (StructTmTy) {
+ StructTmPtrTy = ACtx.getPointerType(*StructTmTy);
+ StructTmPtrRestrictTy = getRestrictTy(*StructTmPtrTy);
+ ConstStructTmPtrTy = ACtx.getPointerType(StructTmTy->withConst());
+ ConstStructTmPtrRestrictTy = getRestrictTy(*ConstStructTmPtrTy);
+ }
+
+ if (ConstTime_tPtrTy && StructTmPtrTy)
+ // struct tm * localtime(const time_t *tp);
+ addToFunctionSummaryMap("localtime",
+ Summary(ArgTypes{*ConstTime_tPtrTy},
+ RetType{*StructTmPtrTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0))));
+
+ if (ConstTime_tPtrRestrictTy && StructTmPtrRestrictTy && StructTmPtrTy)
+ // struct tm *localtime_r(const time_t *restrict timer,
+ // struct tm *restrict result);
+ addToFunctionSummaryMap(
+ "localtime_r",
+ Summary(ArgTypes{*ConstTime_tPtrRestrictTy, *StructTmPtrRestrictTy},
+ RetType{*StructTmPtrTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0)))
+ .ArgConstraint(NotNull(ArgNo(1))));
+
+ if (ConstStructTmPtrRestrictTy)
+ // char *asctime_r(const struct tm *restrict tm, char *restrict buf);
+ addToFunctionSummaryMap(
+ "asctime_r",
+ Summary(ArgTypes{*ConstStructTmPtrRestrictTy, CharPtrRestrictTy},
+ RetType{CharPtrTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0)))
+ .ArgConstraint(NotNull(ArgNo(1))));
+
+ if (ConstTime_tPtrTy)
+ // char *ctime_r(const time_t *timep, char *buf);
+ addToFunctionSummaryMap("ctime_r",
+ Summary(ArgTypes{*ConstTime_tPtrTy, CharPtrTy},
+ RetType{CharPtrTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0)))
+ .ArgConstraint(NotNull(ArgNo(1))));
+
+ if (ConstTime_tPtrRestrictTy && StructTmPtrRestrictTy && StructTmPtrTy)
+ // struct tm *gmtime_r(const time_t *restrict timer,
+ // struct tm *restrict result);
+ addToFunctionSummaryMap(
+ "gmtime_r",
+ Summary(ArgTypes{*ConstTime_tPtrRestrictTy, *StructTmPtrRestrictTy},
+ RetType{*StructTmPtrTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0)))
+ .ArgConstraint(NotNull(ArgNo(1))));
+
+ if (ConstTime_tPtrTy && StructTmPtrTy)
+ // struct tm * gmtime(const time_t *tp);
+ addToFunctionSummaryMap("gmtime",
+ Summary(ArgTypes{*ConstTime_tPtrTy},
+ RetType{*StructTmPtrTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(0))));
+
+ Optional<QualType> Clockid_tTy = lookupType("clockid_t", ACtx);
+
+ if (Clockid_tTy && StructTimespecPtrTy)
+ // int clock_gettime(clockid_t clock_id, struct timespec *tp);
+ addToFunctionSummaryMap(
+ "clock_gettime", Summary(ArgTypes{*Clockid_tTy, *StructTimespecPtrTy},
+ RetType{IntTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(1))));
+
+ Optional<QualType> StructItimervalTy = lookupType("itimerval", ACtx);
+ Optional<QualType> StructItimervalPtrTy;
+ if (StructItimervalTy)
+ StructItimervalPtrTy = ACtx.getPointerType(*StructItimervalTy);
+
+ if (StructItimervalPtrTy)
+ // int getitimer(int which, struct itimerval *curr_value);
+ addToFunctionSummaryMap("getitimer",
+ Summary(ArgTypes{IntTy, *StructItimervalPtrTy},
+ RetType{IntTy}, NoEvalCall)
+ .ArgConstraint(NotNull(ArgNo(1))));
}
// Functions for testing.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits