Replaced CheckNonReentrantFunctions and CheckObsoleteFunctions by generic CheckFunctions which is based on Library (#6529)
This commit is contained in:
parent
517922feb6
commit
57d1196386
610
cfg/posix.cfg
610
cfg/posix.cfg
|
@ -19,6 +19,8 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<!-- The behavior of l64a() is undefined when value is negative. -->
|
||||
<!-- If value is zero, it returns an empty string. -->
|
||||
<valid>0:</valid>
|
||||
</arg>
|
||||
</function>
|
||||
|
@ -213,11 +215,13 @@
|
|||
<!-- int usleep(useconds_t useconds); -->
|
||||
<function name="usleep">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-bool/>
|
||||
<valid>0:999999</valid>
|
||||
</arg>
|
||||
<leak-ignore/>
|
||||
<warn severity="style">Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.
|
||||
The obsolescent function 'usleep' is called. POSIX.1-2001 declares usleep() function obsolescent and POSIX.1-2008 removes it. It is recommended that new applications use the 'nanosleep' or 'setitimer' function.</warn>
|
||||
</function>
|
||||
<!-- void _exit(int status); -->
|
||||
<function name="_exit">
|
||||
|
@ -277,23 +281,168 @@
|
|||
<!-- unsigned int alarm(unsigned int seconds); -->
|
||||
<function name="alarm">
|
||||
<noreturn>false</noreturn>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<leak-ignore/>
|
||||
</function>
|
||||
<!-- struct rpcent *getrpcent(void); -->
|
||||
<function name="getrpcent">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'getrpcent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getrpcent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct rpcent *getrpcbyname(char *name); -->
|
||||
<function name="getrpcbyname">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getrpcbyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getrpcbyname_r'.</warn>
|
||||
</function>
|
||||
<!-- truct rpcent *getrpcbynumber(int number); -->
|
||||
<function name="getrpcbynumber">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getrpcbynumber' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getrpcbynumber_r'.</warn>
|
||||
</function>
|
||||
<!-- struct protoent *getprotoent(void); -->
|
||||
<function name="getprotoent">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'getprotoent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getprotoent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct protoent *getprotobyname(const char *name); -->
|
||||
<function name="getprotobyname">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getprotobyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getprotobyname_r'.</warn>
|
||||
</function>
|
||||
<!-- struct protoent *getprotobynumber(int proto); -->
|
||||
<function name="getservbyport">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getprotobynumber' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getprotobynumber_r'.</warn>
|
||||
</function>
|
||||
<!-- struct servent *getservent(void); -->
|
||||
<function name="getservent">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'getservent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getservent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct servent *getservbyname(const char *name, const char *proto); -->
|
||||
<function name="getservbyname">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getservbyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getservbyname_r'.</warn>
|
||||
</function>
|
||||
<!-- struct servent *getservbyport(int port, const char *proto); -->
|
||||
<function name="getservbyport">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getservbyport' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getservbyport_r'.</warn>
|
||||
</function>
|
||||
<!-- struct netent *getnetent(void); -->
|
||||
<function name="getnetent">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'getnetent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getnetent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct netent *getnetbyname(const char *name); -->
|
||||
<function name="getnetbyname">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'getnetbyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getnetbyname_r'.</warn>
|
||||
</function>
|
||||
<!-- struct netent *getnetbyaddr(uint32_t net, int type); -->
|
||||
<function name="getnetbyaddr">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'getnetbyaddr' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getnetbyaddr_r'.</warn>
|
||||
</function>
|
||||
<!-- struct hostent *gethostent(void); -->
|
||||
<function name="gethostent">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'gethostent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'gethostent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct hostent *gethostbyname(const char *name); -->
|
||||
<function name="gethostbyname">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<leak-ignore/>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="getaddrinfo"/>
|
||||
</function>
|
||||
<!-- struct hostent *gethostbyname2(const char *name, int af); -->
|
||||
<function name="gethostbyname2">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<leak-ignore/>
|
||||
<warn severity="portability">Non reentrant function 'gethostbyname2' called. For threadsafe applications it is recommended to use the reentrant replacement function 'gethostbyname2_r'.</warn>
|
||||
</function>
|
||||
<!-- struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); -->
|
||||
<function name="gethostbyaddr">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
|
@ -305,6 +454,7 @@
|
|||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="getnameinfo"/>
|
||||
</function>
|
||||
<!-- int brk(void *addr); -->
|
||||
<function name="brk">
|
||||
|
@ -560,6 +710,7 @@
|
|||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="utimensat"/>
|
||||
</function>
|
||||
<!-- int utimes(const char *filename, const struct timeval times[2]); -->
|
||||
<function name="utimes">
|
||||
|
@ -735,6 +886,7 @@
|
|||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="rand"/>
|
||||
</function>
|
||||
<function name="memmem">
|
||||
<noreturn>false</noreturn>
|
||||
|
@ -1166,14 +1318,16 @@
|
|||
<!-- pid_t setsid(void); -->
|
||||
<function name="setsid">
|
||||
<noreturn>false</noreturn>
|
||||
<!-- it is a good idea to do: <use-retval/> -->
|
||||
</function>
|
||||
<!-- char *getwd(char *path_name);-->
|
||||
<function name="getwd">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<leak-ignore/>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="getcwd"/>
|
||||
</function>
|
||||
<!-- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/arpa/inet.h.html -->
|
||||
<!-- uint32_t htonl(uint32_t); -->
|
||||
|
@ -1384,8 +1538,9 @@
|
|||
<function name="freeaddrinfo">
|
||||
<noreturn>false</noreturn>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
<!-- not-null is not required by the resource above, but some systems will segfault -->
|
||||
</arg>
|
||||
</function>
|
||||
<!-- int getaddrinfo(const char * nodename, const char * servname, const struct addrinfo * hints, struct addrinfo ** res); -->
|
||||
|
@ -1433,21 +1588,38 @@
|
|||
</function>
|
||||
<!--struct passwd *getpwent(void); -->
|
||||
<function name="getpwent">
|
||||
<use-retval/>
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<warn severity="portability">Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.</warn>
|
||||
</function>
|
||||
<!--struct passwd *getpwnam(const char *); -->
|
||||
<function name="getpwnam">
|
||||
<use-retval/>
|
||||
<noreturn>false</noreturn>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<warn severity="portability">Non reentrant function 'getpwnam' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwnam_r'.</warn>
|
||||
</function>
|
||||
<!-- char *strtok(char *s, const char *ct); -->
|
||||
<function name="strtok,std::strtok">
|
||||
<pure/>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'strtok' called. For threadsafe applications it is recommended to use the reentrant replacement function 'strtok_r'.</warn>
|
||||
</function>
|
||||
<!-- char *strtok_r(char *str, const char *delim, char **saveptr); -->
|
||||
<function name="strtok_r">
|
||||
<pure/>
|
||||
<!-- strtok may modify the first argument, so using the return value is not mandatory -->
|
||||
<noreturn>false</noreturn>
|
||||
<pure/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
|
@ -1470,11 +1642,12 @@
|
|||
</function>
|
||||
<!-- struct passwd *getpwuid(uid_t uid); -->
|
||||
<function name="getpwuid">
|
||||
<use-retval/>
|
||||
<noreturn>false</noreturn>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<warn severity="portability">Non reentrant function 'getpwuid' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwuid_r'.</warn>
|
||||
</function>
|
||||
<!-- int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **); -->
|
||||
<function name="getpwuid_r">
|
||||
|
@ -1672,6 +1845,7 @@
|
|||
<arg nr="4">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="sprintf"/>
|
||||
</function>
|
||||
<!-- char *fcvt(double value, int ndigit, int *restrict decpt, int *restrict sign);-->
|
||||
<!-- LEGACY in POSIX.1-2001, removed in POSIX.1-2008-->
|
||||
|
@ -1689,6 +1863,7 @@
|
|||
<arg nr="4">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="sprintf"/>
|
||||
</function>
|
||||
<!-- char *gcvt(double value, int ndigit, char *buf);-->
|
||||
<!-- LEGACY in POSIX.1-2001, removed in POSIX.1-2008-->
|
||||
|
@ -1703,6 +1878,7 @@
|
|||
<arg nr="3">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="sprintf"/>
|
||||
</function>
|
||||
<!-- off_t lseek(int fildes, off_t offset, int whence); -->
|
||||
<function name="lseek">
|
||||
|
@ -1777,22 +1953,42 @@
|
|||
<function name="unsetenv">
|
||||
<noreturn>false</noreturn>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- struct tm *localtime_r(const time_t *timep, struct tm *result); -->
|
||||
<function name="localtime_r">
|
||||
<!-- struct tm * localtime(const time_t *tp); -->
|
||||
<function name="localtime,std::localtime">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.</warn>
|
||||
</function>
|
||||
<!-- struct tm *localtime_r(const time_t *timep, struct tm *result); -->
|
||||
<function name="localtime_r">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- struct dirent *readdir(DIR *dirp); -->
|
||||
<function name="readdir">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'readdir' called. For threadsafe applications it is recommended to use the reentrant replacement function 'readdir_r'.</warn>
|
||||
</function>
|
||||
<!-- int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); -->
|
||||
<function name="readdir_r">
|
||||
<noreturn>false</noreturn>
|
||||
|
@ -1852,6 +2048,7 @@
|
|||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="strftime"/>
|
||||
</function>
|
||||
<!-- char *ctime_r(const time_t *timep, char *buf); -->
|
||||
<function name="ctime_r">
|
||||
|
@ -1864,6 +2061,7 @@
|
|||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="strftime"/>
|
||||
</function>
|
||||
<!-- struct tm *gmtime_r(const time_t *timep, struct tm *result); -->
|
||||
<function name="gmtime_r">
|
||||
|
@ -1877,6 +2075,17 @@
|
|||
<not-null/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- struct tm * gmtime(const time_t *tp); -->
|
||||
<function name="gmtime">
|
||||
<use-retval/>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'gmtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'gmtime_r'.</warn>
|
||||
</function>
|
||||
<!-- http://pubs.opengroup.org/onlinepubs/007908799/xsh/time.h.html -->
|
||||
<!-- int clock_settime(clockid_t clock_id, const struct timespec *tp); -->
|
||||
<function name="clock_settime">
|
||||
|
@ -1926,6 +2135,380 @@
|
|||
</arg>
|
||||
<arg nr="2"/>
|
||||
</function>
|
||||
<!-- char* tmpnam(char *s); -->
|
||||
<function name="tmpnam,tmpnam_r">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" alternatives="tmpfile,mkstemp,mkdtemp" reason="Obsolescent"/>
|
||||
</function>
|
||||
<!-- void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...); -->
|
||||
<function name="makecontext">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="any"/>
|
||||
<warn severity="portability">Obsolescent function 'makecontext' called. Applications are recommended to be rewritten to use POSIX threads.</warn>
|
||||
</function>
|
||||
<!-- void swapcontext(ucontext_t *restrict oucp, const ucontext_t *restrict ucp); -->
|
||||
<function name="swapcontext">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Obsolescent function 'swapcontext' called. Applications are recommended to be rewritten to use POSIX threads.</warn>
|
||||
</function>
|
||||
<!-- void getcontext(ucontext_t *ucp); -->
|
||||
<function name="getcontext">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Obsolescent function 'getcontext' called. Applications are recommended to be rewritten to use POSIX threads.</warn>
|
||||
</function>
|
||||
<!-- useconds_t ualarm(useconds_t useconds, useconds_t interval); -->
|
||||
<function name="ualarm">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="timer_create,timer_delete,timer_getoverrun,timer_gettime,timer_settime"/>
|
||||
</function>
|
||||
<!-- double scalb(double x, double n); -->
|
||||
<function name="scalb">
|
||||
<noreturn>false</noreturn>
|
||||
<use-retval/>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="scalbln,scalblnf,scalbln,scalbn,scalbnf,scalbnl"/>
|
||||
</function>
|
||||
<!-- void bcopy(const void *s1, void *s2, size_t n); -->
|
||||
<function name="bcopy">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="memcpy,memmove"/>
|
||||
</function>
|
||||
<!-- int bcmp(const void *s1, void *s2, size_t n); -->
|
||||
<function name="bcmp">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="memcmp"/>
|
||||
</function>
|
||||
<!-- void bzero(void *s, size_t n); -->
|
||||
<function name="bzero">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="memset"/>
|
||||
</function>
|
||||
<!-- int ftime(struct timeb *tp); -->
|
||||
<function name="ftime">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="time,gettimeofday,clock_gettime"/>
|
||||
</function>
|
||||
<!-- wchar_t *wcswcs(const wchar_t *ws1, const wchar_t *ws2); -->
|
||||
<function name="wcswcs">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="wcsstr"/>
|
||||
</function>
|
||||
<!-- char *index(const char *s, int c); -->
|
||||
<function name="index">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="strchr"/>
|
||||
</function>
|
||||
<!-- char *rindex(const char *s, int c); -->
|
||||
<function name="rindex">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="strrchr"/>
|
||||
</function>
|
||||
<!-- sighandler_t bsd_signal(int signum, sighandler_t handler); -->
|
||||
<function name="bsd_signal">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="sigaction"/>
|
||||
</function>
|
||||
<!-- pid_t vfork(void); -->
|
||||
<function name="vfork">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="fork"/>
|
||||
</function>
|
||||
<!-- int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr); -->
|
||||
<function name="pthread_attr_setstackaddr">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="pthread_attr_setstack"/>
|
||||
</function>
|
||||
<!-- int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr); -->
|
||||
<function name="pthread_attr_getstackaddr">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="style" reason="Obsolescent" alternatives="pthread_attr_getstack"/>
|
||||
</function>
|
||||
<!-- char *tempnam(const char *dir, const char *pfx); -->
|
||||
<function name="tempnam">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'tempnam' called. For threadsafe applications it is recommended to use the reentrant replacement function 'tempnam_r'.</warn>
|
||||
</function>
|
||||
<!-- char *crypt(const char *key, const char *salt); -->
|
||||
<function name="crypt">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.</warn>
|
||||
</function>
|
||||
<!-- char *ttyname(int fd); -->
|
||||
<function name="ttyname">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'ttyname' called. For threadsafe applications it is recommended to use the reentrant replacement function 'ttyname_r'.</warn>
|
||||
</function>
|
||||
<!-- struct spwd *getspnam(const char *name); -->
|
||||
<function name="getspnam">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getspnam' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getspnam_r'.</warn>
|
||||
</function>
|
||||
<!-- struct spwd *getspent(void); -->
|
||||
<function name="getspent">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<warn severity="portability">Non reentrant function 'getspent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getspent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct spwd *fgetspent(FILE *fp); -->
|
||||
<function name="fgetspent">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'fgetspent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'fgetspent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct spwd *sgetspent(const char *s); -->
|
||||
<function name="sgetspent">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'sgetspent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'sgetspent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct passwd *fgetpwent(FILE *stream); -->
|
||||
<function name="fgetpwent">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'fgetpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'fgetpwent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct group *getgrent(void); -->
|
||||
<function name="getgrent">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<warn severity="portability">Non reentrant function 'getgrent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getgrent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct group *fgetgrent(FILE *stream); -->
|
||||
<function name="fgetgrent">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'fgetgrent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'fgetgrent_r'.</warn>
|
||||
</function>
|
||||
<!-- int getnetgrent(char **host, char **user, char **domain); -->
|
||||
<function name="getnetgrent">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getnetgrent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getnetgrent_r'.</warn>
|
||||
</function>
|
||||
<!-- struct group *getgrnam(const char *name); -->
|
||||
<function name="getgrnam">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getgrnam' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getgrnam_r'.</warn>
|
||||
</function>
|
||||
<!-- struct group *getgrgid(gid_t gid); -->
|
||||
<function name="getgrgid">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="portability">Non reentrant function 'getgrgid' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getgrgid_r'.</warn>
|
||||
</function>
|
||||
<!-- char *getlogin(void); -->
|
||||
<function name="getlogin">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<warn severity="portability">Non reentrant function 'getlogin' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getlogin_r'.</warn>
|
||||
</function>
|
||||
<!-- char *ctermid(char *s); -->
|
||||
<function name="ctermid">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1"/>
|
||||
<warn severity="portability">Non reentrant function 'ctermid' called. For threadsafe applications it is recommended to use the reentrant replacement function 'ctermid_r'.</warn>
|
||||
</function>
|
||||
<memory>
|
||||
<alloc init="true">strdup</alloc>
|
||||
<alloc init="true">strndup</alloc>
|
||||
|
@ -1956,6 +2539,7 @@
|
|||
<alloc init="true">popen</alloc>
|
||||
<dealloc>pclose</dealloc>
|
||||
</resource>
|
||||
<!-- This type definitions refer to http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html-->
|
||||
<podtype name="in_port_t" sign="u" size="2"/>
|
||||
<podtype name="in_addr_t" sign="u" size="4"/>
|
||||
<podtype name="socklen_t" sign="u" size="4"/>
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<warn severity="style" cstd="c99" alternatives="strftime" reason="Obsolete"/>
|
||||
</function>
|
||||
<!-- void assert(int expression) -->
|
||||
<function name="assert">
|
||||
|
@ -1435,12 +1436,14 @@
|
|||
</arg>
|
||||
</function>
|
||||
<!-- char *gets(char *buffer); -->
|
||||
<function name="gets">
|
||||
<function name="gets,std::gets">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<warn severity="warning">Obsolete function 'gets' called. It is recommended to use 'fgets' instead.
|
||||
The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun if the input data exceeds the size of the buffer. It is recommended to use the function 'fgets' instead.</warn>
|
||||
</function>
|
||||
<!-- struct tm * gmtime(const time_t *tp); -->
|
||||
<function name="gmtime,std::gmtime">
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2015 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Check functions
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "checkfunctions.h"
|
||||
#include "symboldatabase.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Register this check class (by creating a static instance of it)
|
||||
namespace {
|
||||
CheckFunctions instance;
|
||||
}
|
||||
|
||||
void CheckFunctions::check()
|
||||
{
|
||||
const bool checkAlloca = (_settings->standards.c >= Standards::C99 && _tokenizer->isC()) || _settings->standards.cpp >= Standards::CPP11;
|
||||
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
for (unsigned int i = 0; i < symbolDatabase->functionScopes.size(); i++) {
|
||||
const Scope* scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||
if (tok->isName() && tok->varId() == 0 && tok->strAt(1) == "(") {
|
||||
// alloca() is special as it depends on the code being C or C++, so it is not in Library
|
||||
if (checkAlloca && Token::Match(tok, "alloca (") && (!tok->function() || tok->function()->nestedIn->type == Scope::eGlobal)) {
|
||||
if (_tokenizer->isC())
|
||||
reportError(tok, Severity::warning, "allocaCalled",
|
||||
"Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n"
|
||||
"The obsolete function 'alloca' is called. In C99 and later it is recommended to use a variable length array or "
|
||||
"a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons "
|
||||
"(http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca).");
|
||||
else
|
||||
reportError(tok, Severity::warning, "allocaCalled",
|
||||
"Obsolete function 'alloca' called. In C++11 and later it is recommended to use std::array<> instead.\n"
|
||||
"The obsolete function 'alloca' is called. In C++11 and later it is recommended to use std::array<> or "
|
||||
"a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons "
|
||||
"(http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca).");
|
||||
} else {
|
||||
if (tok->function() && tok->function()->hasBody())
|
||||
continue;
|
||||
|
||||
const Library::WarnInfo* wi = _settings->library.getWarnInfo(tok);
|
||||
if (wi) {
|
||||
if (_settings->isEnabled(Severity::toString(wi->severity)) && _settings->standards.c >= wi->standards.c && _settings->standards.cpp >= wi->standards.cpp) {
|
||||
reportError(tok, wi->severity, tok->str() + "Called", wi->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,55 +16,60 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef checknonreentrantfunctionsH
|
||||
#define checknonreentrantfunctionsH
|
||||
#ifndef checkfunctionsH
|
||||
#define checkfunctionsH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "config.h"
|
||||
#include "check.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
||||
/// @addtogroup Checks
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief Using non reentrant functions that can be replaced by their reentrant versions
|
||||
* @brief Check for functions which should not be used
|
||||
*/
|
||||
|
||||
class CPPCHECKLIB CheckNonReentrantFunctions : public Check {
|
||||
class CPPCHECKLIB CheckFunctions : public Check {
|
||||
public:
|
||||
/** This constructor is used when registering the CheckNonReentrantFunctions */
|
||||
CheckNonReentrantFunctions() : Check(myName()) {
|
||||
/** This constructor is used when registering the CheckFunctions */
|
||||
CheckFunctions() : Check(myName()) {
|
||||
}
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckNonReentrantFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
CheckFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger) {
|
||||
}
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
||||
CheckNonReentrantFunctions checkNonReentrantFunctions(tokenizer, settings, errorLogger);
|
||||
checkNonReentrantFunctions.nonReentrantFunctions();
|
||||
CheckFunctions checkFunctions(tokenizer, settings, errorLogger);
|
||||
checkFunctions.check();
|
||||
}
|
||||
|
||||
/** Check for non reentrant functions */
|
||||
void nonReentrantFunctions();
|
||||
/** Check for functions that should not be used */
|
||||
void check();
|
||||
|
||||
private:
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||
CheckFunctions c(0, settings, errorLogger);
|
||||
|
||||
static std::string generateErrorMessage(const std::string& function);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const;
|
||||
|
||||
static std::string myName() {
|
||||
return "Non reentrant functions";
|
||||
for (std::map<std::string, Library::WarnInfo>::const_iterator i = settings->library.functionwarn.cbegin(); i != settings->library.functionwarn.cend(); ++i) {
|
||||
c.reportError(0, Severity::style, i->first+"Called", i->second.message);
|
||||
}
|
||||
}
|
||||
|
||||
std::string classInfo() const;
|
||||
static std::string myName() {
|
||||
return "Check function usage";
|
||||
}
|
||||
|
||||
std::string classInfo() const {
|
||||
return "Warn if a function is called whose usage is discouraged\n";
|
||||
}
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
#endif // checknonreentrantfunctionsH
|
||||
#endif // checkfunctionsH
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2015 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Find non reentrant functions
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "checknonreentrantfunctions.h"
|
||||
#include "symboldatabase.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Register this check class (by creating a static instance of it)
|
||||
namespace {
|
||||
CheckNonReentrantFunctions instance;
|
||||
}
|
||||
|
||||
namespace {
|
||||
const std::set<std::string> _nonReentrantFunctions = make_container< std::set<std::string> > ()
|
||||
<< "localtime" << "gmtime" << "strtok" << "gethostbyname" << "gethostbyaddr" << "getservbyname"
|
||||
<< "getservbyport" << "crypt" << "ttyname" << "gethostbyname2"
|
||||
<< "getprotobyname" << "getnetbyname" << "getnetbyaddr" << "getrpcbyname" << "getrpcbynumber" << "getrpcent"
|
||||
<< "ctermid" << "readdir" << "getlogin" << "getpwent" << "getpwnam" << "getpwuid" << "getspent"
|
||||
<< "fgetspent" << "getspnam" << "getgrnam" << "getgrgid" << "getnetgrent" << "tempnam" << "fgetpwent"
|
||||
<< "fgetgrent" << "ecvt" << "gcvt" << "getservent" << "gethostent" << "getgrent" << "fcvt" ;
|
||||
}
|
||||
|
||||
std::string CheckNonReentrantFunctions::generateErrorMessage(const std::string& function)
|
||||
{
|
||||
return std::string("Non reentrant function '") + function + "' called. " +
|
||||
"For threadsafe applications it is recommended to use the reentrant replacement function '" + function + "_r'.";
|
||||
}
|
||||
|
||||
void CheckNonReentrantFunctions::nonReentrantFunctions()
|
||||
{
|
||||
if (!_settings->standards.posix || !_settings->isEnabled("portability"))
|
||||
return;
|
||||
|
||||
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token *tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
// Look for function invocations
|
||||
if (tok->varId() != 0 || !tok->isName() || tok->strAt(1) != "(")
|
||||
continue;
|
||||
|
||||
// Check for non-reentrant function name
|
||||
std::set<std::string>::const_iterator it = _nonReentrantFunctions.find(tok->str());
|
||||
if (it == _nonReentrantFunctions.end())
|
||||
continue;
|
||||
|
||||
const Token *prev = tok->previous();
|
||||
if (prev) {
|
||||
// Ignore function definitions, class members or class definitions
|
||||
if (prev->str() == ".")
|
||||
continue;
|
||||
|
||||
// Check for "std" or global namespace, ignore other namespaces
|
||||
if (_tokenizer->isCPP() && prev->str() == "::" && prev->previous() && prev->previous()->str() != "std" && prev->previous()->isName())
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only affecting multi threaded code, therefore this is "portability"
|
||||
reportError(tok, Severity::portability, "nonreentrantFunctions" + *it, generateErrorMessage(*it));
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CheckNonReentrantFunctions::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const
|
||||
{
|
||||
CheckNonReentrantFunctions c(0, settings, errorLogger);
|
||||
|
||||
std::set<std::string>::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end());
|
||||
for (; it!=itend; ++it) {
|
||||
c.reportError(0, Severity::portability, "nonreentrantFunctions"+*it, generateErrorMessage(*it));
|
||||
}
|
||||
}
|
||||
|
||||
std::string CheckNonReentrantFunctions::classInfo() const
|
||||
{
|
||||
std::string info = "Warn if any of these non reentrant functions are used:\n";
|
||||
std::set<std::string>::const_iterator it(_nonReentrantFunctions.begin()), itend(_nonReentrantFunctions.end());
|
||||
for (; it!=itend; ++it) {
|
||||
info += "- " + *it + "\n";
|
||||
}
|
||||
return info;
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2015 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Obsolete functions
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "checkobsolescentfunctions.h"
|
||||
#include "symboldatabase.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
std::map<std::string, std::string> CheckObsoleteFunctions::_obsoleteStandardFunctions;
|
||||
std::map<std::string, std::string> CheckObsoleteFunctions::_obsoletePosixFunctions;
|
||||
std::map<std::string, std::string> CheckObsoleteFunctions::_obsoleteC99Functions;
|
||||
|
||||
|
||||
// Register this check class (by creating a static instance of it)
|
||||
namespace {
|
||||
CheckObsoleteFunctions instance;
|
||||
}
|
||||
|
||||
void CheckObsoleteFunctions::obsoleteFunctions()
|
||||
{
|
||||
if (!_settings->isEnabled("style"))
|
||||
return;
|
||||
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const bool cStandard = _settings->standards.c >= Standards::C99 ;
|
||||
|
||||
for (unsigned int i = 0; i < symbolDatabase->functionScopes.size(); i++) {
|
||||
const Scope* scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||
if (tok->isName() && tok->varId()==0 && (!tok->function() || !tok->function()->hasBody()) && tok->strAt(1) == "(" &&
|
||||
tok->strAt(-1) != "." && (!Token::Match(tok->tokAt(-2), "%name% ::") || Token::simpleMatch(tok->tokAt(-2), "std ::"))) {
|
||||
|
||||
std::map<std::string,std::string>::const_iterator it = _obsoleteStandardFunctions.find(tok->str());
|
||||
if (it != _obsoleteStandardFunctions.end()) {
|
||||
// If checking an old code base it might be uninteresting to update obsolete functions.
|
||||
reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second);
|
||||
} else {
|
||||
if (_settings->standards.posix) {
|
||||
it = _obsoletePosixFunctions.find(tok->str());
|
||||
if (it != _obsoletePosixFunctions.end()) {
|
||||
// If checking an old code base it might be uninteresting to update obsolete functions.
|
||||
reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second);
|
||||
}
|
||||
}
|
||||
if (cStandard) {
|
||||
// alloca : this function is obsolete in C but not in C++ (#4382)
|
||||
it = _obsoleteC99Functions.find(tok->str());
|
||||
if (it != _obsoleteC99Functions.end() && !(tok->str() == "alloca" && _tokenizer->isCPP())) {
|
||||
reportError(tok, Severity::style, "obsoleteFunctions"+it->first, it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2015 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef checkobsoletefunctionsH
|
||||
#define checkobsoletefunctionsH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "config.h"
|
||||
#include "check.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
||||
/// @addtogroup Checks
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief Using obsolete functions that are always insecure to use.
|
||||
*/
|
||||
|
||||
class CPPCHECKLIB CheckObsoleteFunctions : public Check {
|
||||
public:
|
||||
/** This constructor is used when registering the CheckObsoleteFunctions */
|
||||
CheckObsoleteFunctions() : Check(myName()) {
|
||||
initObsoleteFunctions();
|
||||
}
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckObsoleteFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger) {
|
||||
}
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
||||
CheckObsoleteFunctions checkObsoleteFunctions(tokenizer, settings, errorLogger);
|
||||
checkObsoleteFunctions.obsoleteFunctions();
|
||||
}
|
||||
|
||||
/** Check for obsolete functions */
|
||||
void obsoleteFunctions();
|
||||
|
||||
private:
|
||||
/* function name / error message */
|
||||
static std::map<std::string, std::string> _obsoleteStandardFunctions;
|
||||
static std::map<std::string, std::string> _obsoletePosixFunctions;
|
||||
static std::map<std::string, std::string> _obsoleteC99Functions;
|
||||
|
||||
/** init obsolete functions list ' */
|
||||
static void initObsoleteFunctions() {
|
||||
// Obsolete posix functions, which messages suggest only one alternative and doesn't contain additional information.
|
||||
const struct {
|
||||
const char* bad;
|
||||
const char* good;
|
||||
} posix_stdmsgs[] = {
|
||||
{"bsd_signal", "sigaction"},
|
||||
{"gethostbyaddr", "getnameinfo"},
|
||||
{"gethostbyname", "getaddrinfo"},
|
||||
{"bcmp", "memcmp"},
|
||||
{"bzero", "memset"},
|
||||
{"ecvt", "sprintf"},
|
||||
{"fcvt", "sprintf"},
|
||||
{"gcvt", "sprintf"},
|
||||
{"getwd", "getcwd"},
|
||||
{"index", "strchr"}, // See #2334 (using the Qt Model/View function 'index')
|
||||
{"rindex", "strrchr"},
|
||||
{"pthread_attr_getstackaddr", "pthread_attr_getstack"},
|
||||
{"pthread_attr_setstackaddr", "pthread_attr_setstack"},
|
||||
{"vfork", "fork"},
|
||||
{"wcswcs", "wcsstr"},
|
||||
{"rand_r", "rand"},
|
||||
{"utime", "utimensat"},
|
||||
{"asctime_r", "strftime"},
|
||||
{"ctime_r", "strftime"}
|
||||
};
|
||||
|
||||
for (std::size_t i = 0; i < (sizeof(posix_stdmsgs) / sizeof(*posix_stdmsgs)); ++i) {
|
||||
_obsoletePosixFunctions[posix_stdmsgs[i].bad] = "Obsolete function '" + std::string(posix_stdmsgs[i].bad) + "' called. It is recommended to use the function '" + posix_stdmsgs[i].good + "' instead.";
|
||||
}
|
||||
|
||||
_obsoletePosixFunctions["usleep"] = "Obsolete function 'usleep' called. It is recommended to use the 'nanosleep' or 'setitimer' function instead.\n"
|
||||
"The obsolete function 'usleep' is called. POSIX.1-2001 declares usleep() function obsolete and POSIX.1-2008 removes it. It is recommended that new applications use the 'nanosleep' or 'setitimer' function.";
|
||||
|
||||
_obsoletePosixFunctions["bcopy"] = "Obsolete function 'bcopy' called. It is recommended to use the 'memmove' or 'memcpy' function instead.";
|
||||
|
||||
_obsoletePosixFunctions["ftime"] = "Obsolete function 'ftime' called. It is recommended to use time(), gettimeofday() or clock_gettime() instead.";
|
||||
|
||||
_obsoletePosixFunctions["getcontext"] = "Obsolete function 'getcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
|
||||
_obsoletePosixFunctions["makecontext"] = "Obsolete function 'makecontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
|
||||
_obsoletePosixFunctions["swapcontext"] = "Obsolete function 'swapcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.";
|
||||
|
||||
_obsoletePosixFunctions["scalbln"] = "Obsolete function 'scalb' called. It is recommended to use 'scalbln', 'scalblnf' or 'scalblnl' instead.";
|
||||
|
||||
_obsoletePosixFunctions["ualarm"] = "Obsolete function 'ualarm' called. It is recommended to use 'timer_create', 'timer_delete', 'timer_getoverrun', 'timer_gettime' or 'timer_settime' instead.";
|
||||
|
||||
_obsoletePosixFunctions["tmpnam"] = "Obsolete function 'tmpnam' called. It is recommended to use 'tmpfile', 'mkstemp' or 'mkdtemp' instead.";
|
||||
|
||||
_obsoletePosixFunctions["tmpnam_r"] = "Obsolete function 'tmpnam_r' called. It is recommended to use 'tmpfile', 'mkstemp' or 'mkdtemp' instead.";
|
||||
|
||||
_obsoleteStandardFunctions["gets"] = "Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n"
|
||||
"The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun if the input data exceeds the size of the buffer. It is recommended to use the function 'fgets' instead.";
|
||||
_obsoleteC99Functions["alloca"] = "Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n"
|
||||
"The obsolete function 'alloca' is called. In C99 and later it is recommended to use a variable length array or a dynamically allocated array instead. The function 'alloca' is dangerous for many reasons (http://stackoverflow.com/questions/1018853/why-is-alloca-not-considered-good-practice and http://linux.die.net/man/3/alloca).";
|
||||
_obsoleteC99Functions["asctime"] = "Obsolete function 'asctime' called. It is recommended to use the function 'strftime' instead.";
|
||||
// ctime is obsolete - it's not threadsafe. but there is no good replacement.
|
||||
//_obsoleteC99Functions["ctime"] = "Obsolete function 'ctime' called. It is recommended to use the function 'strftime' instead.";
|
||||
}
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||
CheckObsoleteFunctions c(0, settings, errorLogger);
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it = _obsoleteStandardFunctions.begin(); it != _obsoleteStandardFunctions.end(); ++it)
|
||||
c.reportError(0, Severity::style, "obsoleteFunctions" + it->first, it->second);
|
||||
for (std::map<std::string, std::string>::const_iterator it = _obsoleteC99Functions.begin(); it != _obsoleteC99Functions.end(); ++it)
|
||||
c.reportError(0, Severity::style, "obsoleteFunctions" + it->first, it->second);
|
||||
for (std::map<std::string, std::string>::const_iterator it = _obsoletePosixFunctions.begin(); it != _obsoletePosixFunctions.end(); ++it)
|
||||
c.reportError(0, Severity::style, "obsoleteFunctions" + it->first, it->second);
|
||||
}
|
||||
|
||||
static std::string myName() {
|
||||
return "Obsolete functions";
|
||||
}
|
||||
|
||||
std::string classInfo() const {
|
||||
std::string info = "Warn if any of these obsolete functions are used:\n";
|
||||
for (std::map<std::string, std::string>::const_iterator it = _obsoleteStandardFunctions.begin(); it != _obsoleteStandardFunctions.end(); ++it)
|
||||
info += "- " + it->first + "\n";
|
||||
for (std::map<std::string, std::string>::const_iterator it = _obsoleteC99Functions.begin(); it != _obsoleteC99Functions.end(); ++it)
|
||||
info += "- " + it->first + "\n";
|
||||
for (std::map<std::string, std::string>::const_iterator it = _obsoletePosixFunctions.begin(); it != _obsoletePosixFunctions.end(); ++it)
|
||||
info += "- " + it->first + "\n";
|
||||
return info;
|
||||
}
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
#endif // checkobsoletefunctionsH
|
|
@ -55,15 +55,14 @@
|
|||
<ClCompile Include="checkbufferoverrun.cpp" />
|
||||
<ClCompile Include="checkclass.cpp" />
|
||||
<ClCompile Include="checkcondition.cpp" />
|
||||
<ClCompile Include="checkfunctions.cpp" />
|
||||
<ClCompile Include="checkstring.cpp" />
|
||||
<ClCompile Include="checkexceptionsafety.cpp" />
|
||||
<ClCompile Include="checkinternal.cpp" />
|
||||
<ClCompile Include="checkio.cpp" />
|
||||
<ClCompile Include="checkleakautovar.cpp" />
|
||||
<ClCompile Include="checkmemoryleak.cpp" />
|
||||
<ClCompile Include="checknonreentrantfunctions.cpp" />
|
||||
<ClCompile Include="checknullpointer.cpp" />
|
||||
<ClCompile Include="checkobsolescentfunctions.cpp" />
|
||||
<ClCompile Include="checkother.cpp" />
|
||||
<ClCompile Include="checkpostfixoperator.cpp" />
|
||||
<ClCompile Include="checksizeof.cpp" />
|
||||
|
@ -101,15 +100,14 @@
|
|||
<ClInclude Include="checkbufferoverrun.h" />
|
||||
<ClInclude Include="checkclass.h" />
|
||||
<ClInclude Include="checkcondition.h" />
|
||||
<ClInclude Include="checkfunctions.h" />
|
||||
<ClInclude Include="checkstring.h" />
|
||||
<ClInclude Include="checkexceptionsafety.h" />
|
||||
<ClInclude Include="checkinternal.h" />
|
||||
<ClInclude Include="checkio.h" />
|
||||
<ClInclude Include="checkleakautovar.h" />
|
||||
<ClInclude Include="checkmemoryleak.h" />
|
||||
<ClInclude Include="checknonreentrantfunctions.h" />
|
||||
<ClInclude Include="checknullpointer.h" />
|
||||
<ClInclude Include="checkobsolescentfunctions.h" />
|
||||
<ClInclude Include="checkother.h" />
|
||||
<ClInclude Include="checkpostfixoperator.h" />
|
||||
<ClInclude Include="checksizeof.h" />
|
||||
|
|
|
@ -32,15 +32,9 @@
|
|||
<ClCompile Include="checkmemoryleak.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="checknonreentrantfunctions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="checknullpointer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="checkobsolescentfunctions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="checkother.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -143,6 +137,9 @@
|
|||
<ClCompile Include="astutils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="checkfunctions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="checkbufferoverrun.h">
|
||||
|
@ -157,15 +154,9 @@
|
|||
<ClInclude Include="checkmemoryleak.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="checknonreentrantfunctions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="checknullpointer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="checkobsolescentfunctions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="checkother.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -286,6 +277,9 @@
|
|||
<ClInclude Include="utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="checkfunctions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="version.rc" />
|
||||
|
|
|
@ -621,6 +621,46 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
|||
const tinyxml2::XMLAttribute* scan = functionnode->FindAttribute("scan");
|
||||
const tinyxml2::XMLAttribute* secure = functionnode->FindAttribute("secure");
|
||||
_formatstr[name] = std::make_pair(scan && scan->BoolValue(), secure && secure->BoolValue());
|
||||
} else if (functionnodename == "warn") {
|
||||
WarnInfo wi;
|
||||
const char* const severity = functionnode->Attribute("severity");
|
||||
if (severity == nullptr)
|
||||
return Error(MISSING_ATTRIBUTE, "severity");
|
||||
wi.severity = Severity::fromString(severity);
|
||||
|
||||
const char* const cstd = functionnode->Attribute("cstd");
|
||||
if (cstd) {
|
||||
if (!wi.standards.setC(cstd))
|
||||
return Error(BAD_ATTRIBUTE_VALUE, cstd);
|
||||
} else
|
||||
wi.standards.c = Standards::C89;
|
||||
|
||||
const char* const cppstd = functionnode->Attribute("cppstd");
|
||||
if (cppstd) {
|
||||
if (!wi.standards.setCPP(cppstd))
|
||||
return Error(BAD_ATTRIBUTE_VALUE, cppstd);
|
||||
} else
|
||||
wi.standards.cpp = Standards::CPP03;
|
||||
|
||||
const char* const reason = functionnode->Attribute("reason");
|
||||
const char* const alternatives = functionnode->Attribute("alternatives");
|
||||
if (reason && alternatives) {
|
||||
// Construct message
|
||||
wi.message = std::string(reason) + " function '" + name + "' called. It is recommended to use ";
|
||||
std::vector<std::string> alt = getnames(alternatives);
|
||||
for (std::size_t i = 0; i < alt.size(); ++i) {
|
||||
wi.message += "'" + alt[i] + "'";
|
||||
if (i == alt.size() - 1)
|
||||
wi.message += " instead.";
|
||||
else if (i == alt.size() - 2)
|
||||
wi.message += " or ";
|
||||
else
|
||||
wi.message += ", ";
|
||||
}
|
||||
} else
|
||||
wi.message = functionnode->GetText();
|
||||
|
||||
functionwarn[name] = wi;
|
||||
} else
|
||||
unknown_elements.insert(functionnodename);
|
||||
}
|
||||
|
@ -852,6 +892,16 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
|
|||
return args != callargs;
|
||||
}
|
||||
|
||||
const Library::WarnInfo* Library::getWarnInfo(const Token* ftok) const
|
||||
{
|
||||
if (isNotLibraryFunction(ftok))
|
||||
return nullptr;
|
||||
std::map<std::string, WarnInfo>::const_iterator i = functionwarn.find(functionName(ftok));
|
||||
if (i == functionwarn.cend())
|
||||
return nullptr;
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
bool Library::isUseRetVal(const Token* ftok) const
|
||||
{
|
||||
return (!isNotLibraryFunction(ftok) &&
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "config.h"
|
||||
#include "mathlib.h"
|
||||
#include "token.h"
|
||||
#include "standards.h"
|
||||
#include "errorlogger.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
@ -120,6 +122,15 @@ public:
|
|||
std::set<std::string> functionconst;
|
||||
std::set<std::string> functionpure;
|
||||
|
||||
struct WarnInfo {
|
||||
std::string message;
|
||||
Standards standards;
|
||||
Severity::SeverityType severity;
|
||||
};
|
||||
std::map<std::string, WarnInfo> functionwarn;
|
||||
|
||||
const WarnInfo* getWarnInfo(const Token* ftok) const;
|
||||
|
||||
// returns true if ftok is not a library function
|
||||
bool isNotLibraryFunction(const Token *ftok) const;
|
||||
|
||||
|
|
|
@ -41,6 +41,33 @@ struct Standards {
|
|||
|
||||
/** This constructor clear all the variables **/
|
||||
Standards() : c(C11), cpp(CPP11), posix(false) {}
|
||||
|
||||
bool setC(const std::string& str) {
|
||||
if (str == "c89" || str == "C89") {
|
||||
c = C89;
|
||||
return true;
|
||||
}
|
||||
if (str == "c99" || str == "C99") {
|
||||
c = C99;
|
||||
return true;
|
||||
}
|
||||
if (str == "c11" || str == "C11") {
|
||||
c = C11;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool setCPP(const std::string& str) {
|
||||
if (str == "c++03" || str == "C++03") {
|
||||
cpp = CPP03;
|
||||
return true;
|
||||
}
|
||||
if (str == "c++11" || str == "C++11") {
|
||||
cpp = CPP11;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
*/
|
||||
|
||||
#include "tokenize.h"
|
||||
#include "checkobsolescentfunctions.h"
|
||||
#include "checkfunctions.h"
|
||||
#include "testsuite.h"
|
||||
|
||||
|
||||
class TestObsoleteFunctions : public TestFixture {
|
||||
class TestFunctions : public TestFixture {
|
||||
public:
|
||||
TestObsoleteFunctions() : TestFixture("TestObsoleteFunctions") {
|
||||
TestFunctions() : TestFixture("TestFunctions") {
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -31,8 +31,13 @@ private:
|
|||
|
||||
void run() {
|
||||
settings.addEnabled("style");
|
||||
settings.addEnabled("warning");
|
||||
settings.addEnabled("portability");
|
||||
settings.standards.posix = true;
|
||||
settings.standards.c = Standards::C11;
|
||||
settings.standards.cpp = Standards::CPP11;
|
||||
LOAD_LIB_2(settings.library, "std.cfg");
|
||||
LOAD_LIB_2(settings.library, "posix.cfg");
|
||||
|
||||
TEST_CASE(testbsd_signal);
|
||||
TEST_CASE(testgethostbyname);
|
||||
|
@ -65,8 +70,9 @@ private:
|
|||
// function with body
|
||||
TEST_CASE(test_function_with_body);
|
||||
|
||||
// null pointer dereference in obsoleteFunctions
|
||||
TEST_CASE(ticket3238);
|
||||
// Non-reentrant functions
|
||||
TEST_CASE(test_crypt);
|
||||
TEST_CASE(test_namespace_handling);
|
||||
}
|
||||
|
||||
void check(const char code[], const char filename[]="test.cpp") {
|
||||
|
@ -79,9 +85,9 @@ private:
|
|||
tokenizer.tokenize(istr, filename);
|
||||
tokenizer.simplifyTokenList2();
|
||||
|
||||
// Check for obsolete functions..
|
||||
CheckObsoleteFunctions checkObsoleteFunctions(&tokenizer, &settings, this);
|
||||
checkObsoleteFunctions.obsoleteFunctions();
|
||||
// Check...
|
||||
CheckFunctions checkFunctions(&tokenizer, &settings, this);
|
||||
checkFunctions.check();
|
||||
}
|
||||
|
||||
void testbsd_signal() {
|
||||
|
@ -89,7 +95,7 @@ private:
|
|||
"{\n"
|
||||
" bsd_signal(SIGABRT, SIG_IGN);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'bsd_signal' called. It is recommended to use the function 'sigaction' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolescent function 'bsd_signal' called. It is recommended to use 'sigaction' instead.\n", errout.str());
|
||||
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
|
@ -108,7 +114,7 @@ private:
|
|||
" exit(1);\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'gethostbyname' called. It is recommended to use the function 'getaddrinfo' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'gethostbyname' called. It is recommended to use 'getaddrinfo' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
void testgethostbyaddr() {
|
||||
|
@ -120,7 +126,7 @@ private:
|
|||
" exit(1);\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (style) Obsolete function 'gethostbyaddr' called. It is recommended to use the function 'getnameinfo' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5]: (style) Obsolescent function 'gethostbyaddr' called. It is recommended to use 'getnameinfo' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
void testusleep() {
|
||||
|
@ -128,7 +134,7 @@ private:
|
|||
"{\n"
|
||||
" usleep( 1000 );\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'usleep' called. It is recommended to use the 'nanosleep' or 'setitimer' function instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
void testindex() {
|
||||
|
@ -168,7 +174,7 @@ private:
|
|||
" const char i = index(var, 0);\n"
|
||||
" return i;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'index' called. It is recommended to use the function 'strchr' instead.\n",
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead.\n",
|
||||
errout.str());
|
||||
}
|
||||
|
||||
|
@ -176,7 +182,7 @@ private:
|
|||
check("void TDataModel::forceRowRefresh(int row) {\n"
|
||||
" emit dataChanged(index(row, 0), index(row, columnCount() - 1));\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) Obsolete function 'index' called. It is recommended to use the function 'strchr' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
void testrindex() {
|
||||
|
@ -191,7 +197,7 @@ private:
|
|||
" const char var[7] = \"rindex\";\n"
|
||||
" print(rindex(var, 0));\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'rindex' called. It is recommended to use the function 'strrchr' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'rindex' called. It is recommended to use 'strrchr' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
@ -207,29 +213,45 @@ private:
|
|||
void testgets() {
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *x = gets();\n"
|
||||
" char *x = gets(a);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n", errout.str());
|
||||
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" foo(x, gets());\n"
|
||||
" foo(x, gets(a));\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
void testalloca() {
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *x = alloca(10);\n"
|
||||
"}\n", "test.cpp"); // #4382 - there are no VLAs in C++
|
||||
"}", "test.cpp"); // #4382 - there are no VLAs in C++
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'alloca' called. In C++11 and later it is recommended to use std::array<> instead.\n", errout.str());
|
||||
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *x = alloca(10);\n"
|
||||
"}", "test.c");
|
||||
ASSERT_EQUALS("[test.c:3]: (warning) Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n", errout.str());
|
||||
|
||||
settings.standards.c = Standards::C89;
|
||||
settings.standards.cpp = Standards::CPP03;
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *x = alloca(10);\n"
|
||||
"}", "test.cpp"); // #4382 - there are no VLAs in C++
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *x = alloca(10);\n"
|
||||
"}\n", "test.c");
|
||||
ASSERT_EQUALS("[test.c:3]: (style) Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n", errout.str());
|
||||
"}", "test.c");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
settings.standards.c = Standards::C11;
|
||||
settings.standards.cpp = Standards::CPP11;
|
||||
}
|
||||
|
||||
// ticket #3121
|
||||
|
@ -253,8 +275,8 @@ private:
|
|||
" char *x = std::gets(str);\n"
|
||||
" char *y = gets(str);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n"
|
||||
"[test.cpp:4]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n"
|
||||
"[test.cpp:4]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
// multiple use
|
||||
|
@ -264,8 +286,8 @@ private:
|
|||
" char *x = std::gets(str);\n"
|
||||
" usleep( 1000 );\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n"
|
||||
"[test.cpp:4]: (style) Obsolete function 'usleep' called. It is recommended to use the 'nanosleep' or 'setitimer' function instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n"
|
||||
"[test.cpp:4]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.\n", errout.str());
|
||||
}
|
||||
|
||||
void test_c_declaration() {
|
||||
|
@ -275,14 +297,14 @@ private:
|
|||
" char s [ 10 ] ;\n"
|
||||
" gets ( s ) ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:5]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n", errout.str());
|
||||
|
||||
check("int getcontext(ucontext_t *ucp);\n"
|
||||
"int f (ucontext_t *ucp)\n"
|
||||
"{\n"
|
||||
" getcontext ( ucp ) ;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Obsolete function 'getcontext' called. Due to portability issues, applications are recommended to be rewritten to use POSIX threads.\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4]: (portability) Obsolescent function 'getcontext' called. Applications are recommended to be rewritten to use POSIX threads.\n", errout.str());
|
||||
}
|
||||
|
||||
void test_function_with_body() {
|
||||
|
@ -295,11 +317,81 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void ticket3238() {
|
||||
check("__FBSDID(\"...\");\n");
|
||||
void test_crypt() {
|
||||
check("void f(char *pwd)\n"
|
||||
"{\n"
|
||||
" char *cpwd;"
|
||||
" crypt(pwd, cpwd);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str());
|
||||
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *pwd = getpass(\"Password:\");"
|
||||
" char *cpwd;"
|
||||
" crypt(pwd, cpwd);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str());
|
||||
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" int crypt = 0;"
|
||||
" return crypt;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void test_namespace_handling() {
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" time_t t = 0;"
|
||||
" std::localtime(&t);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str());
|
||||
|
||||
// Passed as function argument
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" printf(\"Magic guess: %d\n\", getpwent());\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str());
|
||||
|
||||
// Pass return value
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" time_t t = 0;"
|
||||
" struct tm *foo = localtime(&t);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str());
|
||||
|
||||
// Access via global namespace
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" ::getpwent();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str());
|
||||
|
||||
// Be quiet on function definitions
|
||||
check("int getpwent()\n"
|
||||
"{\n"
|
||||
" return 123;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// Be quiet on other namespaces
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" foobar::getpwent();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// Be quiet on class member functions
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" foobar.getpwent();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestObsoleteFunctions)
|
||||
REGISTER_TEST(TestFunctions)
|
|
@ -206,6 +206,7 @@ private:
|
|||
TEST_CASE(garbageCode155); // #7118
|
||||
TEST_CASE(garbageCode156); // #7120
|
||||
TEST_CASE(garbageCode157); // #7131
|
||||
TEST_CASE(garbageCode158); // #3238
|
||||
|
||||
TEST_CASE(garbageValueFlow);
|
||||
TEST_CASE(garbageSymbolDatabase);
|
||||
|
@ -1241,6 +1242,11 @@ private:
|
|||
"template std::swap\n"), InternalError);
|
||||
}
|
||||
|
||||
void garbageCode158() { // #3238
|
||||
checkCode("__FBSDID(\"...\");\n");
|
||||
}
|
||||
|
||||
|
||||
void garbageValueFlow() {
|
||||
// #6089
|
||||
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"
|
||||
|
|
|
@ -40,6 +40,7 @@ private:
|
|||
TEST_CASE(function_arg_valid);
|
||||
TEST_CASE(function_arg_minsize);
|
||||
TEST_CASE(function_namespace);
|
||||
TEST_CASE(function_warn);
|
||||
TEST_CASE(memory);
|
||||
TEST_CASE(memory2); // define extra "free" allocation functions
|
||||
TEST_CASE(resource);
|
||||
|
@ -305,6 +306,42 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void function_warn() const {
|
||||
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
" <function name=\"a\">\n"
|
||||
" <warn severity=\"style\" cstd=\"c99\">Message</warn>\n"
|
||||
" </function>\n"
|
||||
" <function name=\"b\">\n"
|
||||
" <warn severity=\"performance\" cppstd=\"c++11\" reason=\"Obsolescent\" alternatives=\"c,d,e\"/>\n"
|
||||
" </function>\n"
|
||||
"</def>";
|
||||
|
||||
Library library;
|
||||
readLibrary(library, xmldata);
|
||||
|
||||
TokenList tokenList(nullptr);
|
||||
std::istringstream istr("a(); b();");
|
||||
tokenList.createTokens(istr);
|
||||
|
||||
const Library::WarnInfo* a = library.getWarnInfo(tokenList.front());
|
||||
const Library::WarnInfo* b = library.getWarnInfo(tokenList.front()->tokAt(4));
|
||||
|
||||
ASSERT_EQUALS(2, library.functionwarn.size());
|
||||
ASSERT(a && b);
|
||||
if (a && b) {
|
||||
ASSERT_EQUALS("Message", a->message);
|
||||
ASSERT_EQUALS(Severity::style, a->severity);
|
||||
ASSERT_EQUALS(Standards::C99, a->standards.c);
|
||||
ASSERT_EQUALS(Standards::CPP03, a->standards.cpp);
|
||||
|
||||
ASSERT_EQUALS("Obsolescent function 'b' called. It is recommended to use 'c', 'd' or 'e' instead.", b->message);
|
||||
ASSERT_EQUALS(Severity::performance, b->severity);
|
||||
ASSERT_EQUALS(Standards::C89, b->standards.c);
|
||||
ASSERT_EQUALS(Standards::CPP11, b->standards.cpp);
|
||||
}
|
||||
}
|
||||
|
||||
void memory() const {
|
||||
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
|
||||
"<def>\n"
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2015 Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tokenize.h"
|
||||
#include "checknonreentrantfunctions.h"
|
||||
#include "testsuite.h"
|
||||
|
||||
|
||||
class TestNonReentrantFunctions : public TestFixture {
|
||||
public:
|
||||
TestNonReentrantFunctions() : TestFixture("TestNonReentrantFunctions") {
|
||||
}
|
||||
|
||||
private:
|
||||
Settings settings;
|
||||
|
||||
void run() {
|
||||
settings.standards.posix = true;
|
||||
settings.addEnabled("portability");
|
||||
|
||||
TEST_CASE(test_crypt);
|
||||
TEST_CASE(test_namespace_handling);
|
||||
}
|
||||
|
||||
void check(const char code[]) {
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.simplifyTokenList2();
|
||||
|
||||
// Check for non reentrant functions..
|
||||
CheckNonReentrantFunctions checkNonReentrantFunctions(&tokenizer, &settings, this);
|
||||
checkNonReentrantFunctions.nonReentrantFunctions();
|
||||
}
|
||||
|
||||
void test_crypt() {
|
||||
check("void f(char *pwd)\n"
|
||||
"{\n"
|
||||
" char *cpwd;"
|
||||
" crypt(pwd, cpwd);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str());
|
||||
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" char *pwd = getpass(\"Password:\");"
|
||||
" char *cpwd;"
|
||||
" crypt(pwd, cpwd);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str());
|
||||
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" int crypt = 0;"
|
||||
" return crypt;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void test_namespace_handling() {
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" time_t t = 0;"
|
||||
" std::localtime(&t);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str());
|
||||
|
||||
// Passed as function argument
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" printf(\"Magic guess: %d\n\", getpwent());\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str());
|
||||
|
||||
// Pass return value
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" time_t t = 0;"
|
||||
" struct tm *foo = localtime(&t);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str());
|
||||
|
||||
// Access via global namespace
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" ::getpwent();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str());
|
||||
|
||||
// Be quiet on function definitions
|
||||
check("int getpwent()\n"
|
||||
"{\n"
|
||||
" return 123;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// Be quiet on other namespaces
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" foobar::getpwent();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// Be quiet on class member functions
|
||||
check("int f()\n"
|
||||
"{\n"
|
||||
" foobar.getpwent();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestNonReentrantFunctions)
|
|
@ -53,9 +53,8 @@
|
|||
<ClCompile Include="testlibrary.cpp" />
|
||||
<ClCompile Include="testmathlib.cpp" />
|
||||
<ClCompile Include="testmemleak.cpp" />
|
||||
<ClCompile Include="testnonreentrantfunctions.cpp" />
|
||||
<ClCompile Include="testnullpointer.cpp" />
|
||||
<ClCompile Include="testobsolescentfunctions.cpp" />
|
||||
<ClCompile Include="testfunctions.cpp" />
|
||||
<ClCompile Include="testoptions.cpp" />
|
||||
<ClCompile Include="testother.cpp" />
|
||||
<ClCompile Include="testpath.cpp" />
|
||||
|
|
|
@ -64,15 +64,9 @@
|
|||
<ClCompile Include="testmemleak.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testnonreentrantfunctions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testnullpointer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testobsolescentfunctions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testoptions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -205,6 +199,9 @@
|
|||
<ClCompile Include="testtokenlist.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testfunctions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="options.h">
|
||||
|
|
Loading…
Reference in New Issue