diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -781,6 +781,7 @@ auto getRestrictTy = [&ACtx](QualType Ty) { return ACtx.getLangOpts().C99 ? ACtx.getRestrictType(Ty) : Ty; }; + auto getPointerTy = [&ACtx](QualType Ty) { return ACtx.getPointerType(Ty); }; // These types are useful for writing specifications quickly, // New specifications should probably introduce more types. @@ -797,21 +798,23 @@ const QualType SizeTy = ACtx.getSizeType(); const QualType VoidPtrTy = ACtx.VoidPtrTy; // void * - const QualType IntPtrTy = ACtx.getPointerType(IntTy); // int * + const QualType IntPtrTy = getPointerTy(IntTy); // int * const QualType UnsignedIntPtrTy = - ACtx.getPointerType(UnsignedIntTy); // unsigned int * + getPointerTy(UnsignedIntTy); // unsigned int * const QualType VoidPtrRestrictTy = getRestrictTy(VoidPtrTy); const QualType ConstVoidPtrTy = - ACtx.getPointerType(ACtx.VoidTy.withConst()); // const void * - const QualType CharPtrTy = ACtx.getPointerType(ACtx.CharTy); // char * + getPointerTy(ACtx.VoidTy.withConst()); // const void * + const QualType CharPtrTy = getPointerTy(ACtx.CharTy); // char * const QualType CharPtrRestrictTy = getRestrictTy(CharPtrTy); const QualType ConstCharPtrTy = - ACtx.getPointerType(ACtx.CharTy.withConst()); // const char * + getPointerTy(ACtx.CharTy.withConst()); // const char * const QualType ConstCharPtrRestrictTy = getRestrictTy(ConstCharPtrTy); - const QualType Wchar_tPtrTy = ACtx.getPointerType(ACtx.WCharTy); // wchar_t * + const QualType Wchar_tPtrTy = getPointerTy(ACtx.WCharTy); // wchar_t * const QualType ConstWchar_tPtrTy = - ACtx.getPointerType(ACtx.WCharTy.withConst()); // const wchar_t * + getPointerTy(ACtx.WCharTy.withConst()); // const wchar_t * const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy); + const QualType SizePtrTy = getPointerTy(SizeTy); + const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy); const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue(); const RangeInt UnsignedIntMax = @@ -883,6 +886,11 @@ for (const Summary &S : Summaries) operator()(Name, S); } + // Add the same summary for different names. + void operator()(std::vector Names, Summary S) { + for (StringRef Name : Names) + operator()(Name, S); + } } addToFunctionSummaryMap(ACtx, FunctionSummaryMap, DisplayLoadedSummaries); // We are finally ready to define specifications for all supported functions. @@ -942,7 +950,7 @@ Optional FilePtrTy, FilePtrRestrictTy; if (FileTy) { // FILE * - FilePtrTy = ACtx.getPointerType(*FileTy); + FilePtrTy = getPointerTy(*FileTy); // FILE *restrict FilePtrRestrictTy = getRestrictTy(*FilePtrTy); } @@ -1262,7 +1270,7 @@ Optional DirTy = lookupType("DIR", ACtx); Optional DirPtrTy; if (DirTy) - DirPtrTy = ACtx.getPointerType(*DirTy); + DirPtrTy = getPointerTy(*DirTy); if (DirPtrTy) // int dirfd(DIR *dirp); @@ -1449,7 +1457,7 @@ Optional StructStatTy = lookupType("stat", ACtx); Optional StructStatPtrTy, StructStatPtrRestrictTy; if (StructStatTy) { - StructStatPtrTy = ACtx.getPointerType(*StructStatTy); + StructStatPtrTy = getPointerTy(*StructStatTy); StructStatPtrRestrictTy = getRestrictTy(*StructStatPtrTy); } @@ -1694,7 +1702,7 @@ RetType{CharPtrTy}, NoEvalCall) .ArgConstraint(NotNull(ArgNo(0)))); - QualType CharPtrConstPtr = ACtx.getPointerType(CharPtrTy.withConst()); + QualType CharPtrConstPtr = getPointerTy(CharPtrTy.withConst()); // int execv(const char *path, char *const argv[]); addToFunctionSummaryMap("execv", @@ -1721,9 +1729,8 @@ Optional StructSockaddrPtrTy, ConstStructSockaddrPtrTy, StructSockaddrPtrRestrictTy, ConstStructSockaddrPtrRestrictTy; if (StructSockaddrTy) { - StructSockaddrPtrTy = ACtx.getPointerType(*StructSockaddrTy); - ConstStructSockaddrPtrTy = - ACtx.getPointerType(StructSockaddrTy->withConst()); + StructSockaddrPtrTy = getPointerTy(*StructSockaddrTy); + ConstStructSockaddrPtrTy = getPointerTy(StructSockaddrTy->withConst()); StructSockaddrPtrRestrictTy = getRestrictTy(*StructSockaddrPtrTy); ConstStructSockaddrPtrRestrictTy = getRestrictTy(*ConstStructSockaddrPtrTy); @@ -1733,7 +1740,7 @@ Optional Socklen_tMax; if (Socklen_tTy) { Socklen_tMax = BVF.getMaxValue(*Socklen_tTy).getLimitedValue(); - Socklen_tPtrTy = ACtx.getPointerType(*Socklen_tTy); + Socklen_tPtrTy = getPointerTy(*Socklen_tTy); Socklen_tPtrRestrictTy = getRestrictTy(*Socklen_tPtrTy); } @@ -1900,8 +1907,8 @@ Optional StructMsghdrTy = lookupType("msghdr", ACtx); Optional StructMsghdrPtrTy, ConstStructMsghdrPtrTy; if (StructMsghdrTy) { - StructMsghdrPtrTy = ACtx.getPointerType(*StructMsghdrTy); - ConstStructMsghdrPtrTy = ACtx.getPointerType(StructMsghdrTy->withConst()); + StructMsghdrPtrTy = getPointerTy(*StructMsghdrTy); + ConstStructMsghdrPtrTy = getPointerTy(StructMsghdrTy->withConst()); } if (Ssize_tTy && StructMsghdrPtrTy) @@ -1986,6 +1993,125 @@ BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5))) .ArgConstraint( ArgumentCondition(5, WithinRange, Range(0, *Socklen_tMax)))); + + Optional Pthread_cond_tTy = lookupType("pthread_cond_t", ACtx); + Optional Pthread_cond_tPtrTy; + if (Pthread_cond_tTy) + Pthread_cond_tPtrTy = getPointerTy(*Pthread_cond_tTy); + + if (Pthread_cond_tPtrTy) + // int pthread_cond_signal(pthread_cond_t *cond); + // int pthread_cond_broadcast(pthread_cond_t *cond); + addToFunctionSummaryMap( + {"pthread_cond_signal", "pthread_cond_broadcast"}, + Summary(ArgTypes{*Pthread_cond_tPtrTy}, RetType{IntTy}, NoEvalCall) + .ArgConstraint(NotNull(ArgNo(0)))); + + Optional Pthread_tTy = lookupType("pthread_t", ACtx); + Optional Pthread_tPtrTy, Pthread_tPtrRestrictTy; + if (Pthread_tTy) { + Pthread_tPtrTy = getPointerTy(*Pthread_tTy); + Pthread_tPtrRestrictTy = getRestrictTy(*Pthread_tPtrTy); + } + + Optional Pthread_mutex_tTy = lookupType("pthread_mutex_t", ACtx); + Optional Pthread_mutex_tPtrTy, Pthread_mutex_tPtrRestrictTy; + if (Pthread_mutex_tTy) { + Pthread_mutex_tPtrTy = getPointerTy(*Pthread_mutex_tTy); + Pthread_mutex_tPtrRestrictTy = getRestrictTy(*Pthread_mutex_tPtrTy); + } + + Optional Pthread_attr_tTy = lookupType("pthread_attr_t", ACtx); + Optional Pthread_attr_tPtrTy, ConstPthread_attr_tPtrTy, + ConstPthread_attr_tPtrRestrictTy; + if (Pthread_attr_tTy) { + Pthread_attr_tPtrTy = getPointerTy(*Pthread_attr_tTy); + ConstPthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy->withConst()); + ConstPthread_attr_tPtrRestrictTy = + getRestrictTy(*ConstPthread_attr_tPtrTy); + } + + Optional Pthread_mutexattr_tTy = + lookupType("pthread_mutexattr_t", ACtx); + Optional Pthread_mutexattr_tPtrTy, ConstPthread_mutexattr_tPtrTy, + ConstPthread_mutexattr_tPtrRestrictTy; + if (Pthread_mutexattr_tTy) { + Pthread_mutexattr_tPtrTy = getPointerTy(*Pthread_mutexattr_tTy); + ConstPthread_mutexattr_tPtrTy = + getPointerTy(Pthread_mutexattr_tTy->withConst()); + ConstPthread_mutexattr_tPtrRestrictTy = + getRestrictTy(*ConstPthread_mutexattr_tPtrTy); + } + + QualType PthreadStartRoutineTy = getPointerTy( + ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy, + FunctionProtoType::ExtProtoInfo())); + + if (Pthread_tPtrRestrictTy && ConstPthread_attr_tPtrRestrictTy) + // int pthread_create(pthread_t *restrict thread, + // const pthread_attr_t *restrict attr, + // void *(*start_routine)(void*), void *restrict arg); + addToFunctionSummaryMap( + "pthread_create", + Summary(ArgTypes{*Pthread_tPtrRestrictTy, + *ConstPthread_attr_tPtrRestrictTy, + PthreadStartRoutineTy, VoidPtrRestrictTy}, + RetType{IntTy}, NoEvalCall) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint(NotNull(ArgNo(2)))); + + if (Pthread_attr_tPtrTy) + // int pthread_attr_destroy(pthread_attr_t *attr); + // int pthread_attr_init(pthread_attr_t *attr); + addToFunctionSummaryMap( + {"pthread_attr_destroy", "pthread_attr_init"}, + Summary(ArgTypes{*Pthread_attr_tPtrTy}, RetType{IntTy}, NoEvalCall) + .ArgConstraint(NotNull(ArgNo(0)))); + + if (ConstPthread_attr_tPtrRestrictTy) + // int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, + // size_t *restrict stacksize); + // int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, + // size_t *restrict guardsize); + addToFunctionSummaryMap( + {"pthread_attr_getstacksize", "pthread_attr_getguardsize"}, + Summary( + ArgTypes{*ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy}, + RetType{IntTy}, NoEvalCall) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint(NotNull(ArgNo(1)))); + + if (Pthread_attr_tPtrTy) + // int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); + // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); + addToFunctionSummaryMap( + {"pthread_attr_setstacksize", "pthread_attr_setguardsize"}, + Summary(ArgTypes{*Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}, + NoEvalCall) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint( + ArgumentCondition(1, WithinRange, Range(0, SizeMax)))); + + if (Pthread_mutex_tPtrRestrictTy && ConstPthread_mutexattr_tPtrRestrictTy) + // int pthread_mutex_init(pthread_mutex_t *restrict mutex, const + // pthread_mutexattr_t *restrict attr); + addToFunctionSummaryMap( + "pthread_mutex_init", + Summary(ArgTypes{*Pthread_mutex_tPtrRestrictTy, + *ConstPthread_mutexattr_tPtrRestrictTy}, + RetType{IntTy}, NoEvalCall) + .ArgConstraint(NotNull(ArgNo(0)))); + + if (Pthread_mutex_tPtrTy) + // int pthread_mutex_destroy(pthread_mutex_t *mutex); + // int pthread_mutex_lock(pthread_mutex_t *mutex); + // int pthread_mutex_trylock(pthread_mutex_t *mutex); + // int pthread_mutex_unlock(pthread_mutex_t *mutex); + addToFunctionSummaryMap( + {"pthread_mutex_destroy", "pthread_mutex_lock", + "pthread_mutex_trylock", "pthread_mutex_unlock"}, + Summary(ArgTypes{*Pthread_mutex_tPtrTy}, RetType{IntTy}, NoEvalCall) + .ArgConstraint(NotNull(ArgNo(0)))); } // Functions for testing. diff --git a/clang/test/Analysis/std-c-library-functions-POSIX.c b/clang/test/Analysis/std-c-library-functions-POSIX.c --- a/clang/test/Analysis/std-c-library-functions-POSIX.c +++ b/clang/test/Analysis/std-c-library-functions-POSIX.c @@ -95,6 +95,20 @@ // 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 pthread_cond_signal(pthread_cond_t *cond) +// CHECK: Loaded summary for: int pthread_cond_broadcast(pthread_cond_t *cond) +// CHECK: Loaded summary for: int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg) +// CHECK: Loaded summary for: int pthread_attr_destroy(pthread_attr_t *attr) +// CHECK: Loaded summary for: int pthread_attr_init(pthread_attr_t *attr) +// CHECK: Loaded summary for: int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, size_t *restrict stacksize) +// CHECK: Loaded summary for: int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, size_t *restrict guardsize) +// CHECK: Loaded summary for: int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +// CHECK: Loaded summary for: int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) +// CHECK: Loaded summary for: int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr) +// CHECK: Loaded summary for: int pthread_mutex_destroy(pthread_mutex_t *mutex) +// CHECK: Loaded summary for: int pthread_mutex_lock(pthread_mutex_t *mutex) +// CHECK: Loaded summary for: int pthread_mutex_trylock(pthread_mutex_t *mutex) +// CHECK: Loaded summary for: int pthread_mutex_unlock(pthread_mutex_t *mutex) long a64l(const char *str64); char *l64a(long value); @@ -227,6 +241,26 @@ 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); +typedef union { int x; } pthread_cond_t; +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_broadcast(pthread_cond_t *cond); +typedef union { int x; } pthread_attr_t; +typedef unsigned long int pthread_t; +int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg); +int pthread_attr_destroy(pthread_attr_t *attr); +int pthread_attr_init(pthread_attr_t *attr); +int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, size_t *restrict stacksize); +int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, size_t *restrict guardsize); +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); +int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); +typedef union { int x; } pthread_mutex_t; +typedef union { int x; } pthread_mutexattr_t; +int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); +int pthread_mutex_destroy(pthread_mutex_t *mutex); +int pthread_mutex_lock(pthread_mutex_t *mutex); +int pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_mutex_unlock(pthread_mutex_t *mutex); + // Must have at least one call expression to initialize the summary map. int bar(void); void foo() {