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 @@ -812,6 +812,8 @@ const QualType ConstWchar_tPtrTy = ACtx.getPointerType(ACtx.WCharTy.withConst()); // const wchar_t * const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy); + const QualType SizePtrTy = ACtx.getPointerType(SizeTy); + const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy); const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue(); const RangeInt UnsignedIntMax = @@ -883,6 +885,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. @@ -1986,6 +1993,126 @@ 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 = ACtx.getPointerType(*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 = ACtx.getPointerType(*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 = ACtx.getPointerType(*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 = ACtx.getPointerType(*Pthread_attr_tTy); + ConstPthread_attr_tPtrTy = + ACtx.getPointerType(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 = ACtx.getPointerType(*Pthread_mutexattr_tTy); + ConstPthread_mutexattr_tPtrTy = + ACtx.getPointerType(Pthread_mutexattr_tTy->withConst()); + ConstPthread_mutexattr_tPtrRestrictTy = + getRestrictTy(*ConstPthread_mutexattr_tPtrTy); + } + + QualType PthreadStartRoutineTy = ACtx.getPointerType( + 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() {