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/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<!-- The behavior of l64a() is undefined when value is negative. -->
|
||||||
|
<!-- If value is zero, it returns an empty string. -->
|
||||||
<valid>0:</valid>
|
<valid>0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
|
@ -213,11 +215,13 @@
|
||||||
<!-- int usleep(useconds_t useconds); -->
|
<!-- int usleep(useconds_t useconds); -->
|
||||||
<function name="usleep">
|
<function name="usleep">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-bool/>
|
<not-bool/>
|
||||||
<valid>0:999999</valid>
|
<valid>0:999999</valid>
|
||||||
</arg>
|
</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>
|
</function>
|
||||||
<!-- void _exit(int status); -->
|
<!-- void _exit(int status); -->
|
||||||
<function name="_exit">
|
<function name="_exit">
|
||||||
|
@ -277,23 +281,168 @@
|
||||||
<!-- unsigned int alarm(unsigned int seconds); -->
|
<!-- unsigned int alarm(unsigned int seconds); -->
|
||||||
<function name="alarm">
|
<function name="alarm">
|
||||||
<noreturn>false</noreturn>
|
<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/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</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>
|
</function>
|
||||||
<!-- struct hostent *gethostbyname(const char *name); -->
|
<!-- struct hostent *gethostbyname(const char *name); -->
|
||||||
<function name="gethostbyname">
|
<function name="gethostbyname">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<use-retval/>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
|
<not-uninit/>
|
||||||
<not-null/>
|
<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/>
|
<not-uninit/>
|
||||||
</arg>
|
</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>
|
</function>
|
||||||
<!-- struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); -->
|
<!-- struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type); -->
|
||||||
<function name="gethostbyaddr">
|
<function name="gethostbyaddr">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
|
<use-retval/>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
|
@ -305,6 +454,7 @@
|
||||||
<arg nr="3">
|
<arg nr="3">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="getnameinfo"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- int brk(void *addr); -->
|
<!-- int brk(void *addr); -->
|
||||||
<function name="brk">
|
<function name="brk">
|
||||||
|
@ -560,6 +710,7 @@
|
||||||
<arg nr="2">
|
<arg nr="2">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="utimensat"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- int utimes(const char *filename, const struct timeval times[2]); -->
|
<!-- int utimes(const char *filename, const struct timeval times[2]); -->
|
||||||
<function name="utimes">
|
<function name="utimes">
|
||||||
|
@ -735,6 +886,7 @@
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="rand"/>
|
||||||
</function>
|
</function>
|
||||||
<function name="memmem">
|
<function name="memmem">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
|
@ -1166,14 +1318,16 @@
|
||||||
<!-- pid_t setsid(void); -->
|
<!-- pid_t setsid(void); -->
|
||||||
<function name="setsid">
|
<function name="setsid">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
|
<!-- it is a good idea to do: <use-retval/> -->
|
||||||
</function>
|
</function>
|
||||||
<!-- char *getwd(char *path_name);-->
|
<!-- char *getwd(char *path_name);-->
|
||||||
<function name="getwd">
|
<function name="getwd">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<leak-ignore/>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="getcwd"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/arpa/inet.h.html -->
|
<!-- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/arpa/inet.h.html -->
|
||||||
<!-- uint32_t htonl(uint32_t); -->
|
<!-- uint32_t htonl(uint32_t); -->
|
||||||
|
@ -1384,8 +1538,9 @@
|
||||||
<function name="freeaddrinfo">
|
<function name="freeaddrinfo">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-null/>
|
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<not-null/>
|
||||||
|
<!-- not-null is not required by the resource above, but some systems will segfault -->
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<!-- int getaddrinfo(const char * nodename, const char * servname, const struct addrinfo * hints, struct addrinfo ** res); -->
|
<!-- int getaddrinfo(const char * nodename, const char * servname, const struct addrinfo * hints, struct addrinfo ** res); -->
|
||||||
|
@ -1433,21 +1588,38 @@
|
||||||
</function>
|
</function>
|
||||||
<!--struct passwd *getpwent(void); -->
|
<!--struct passwd *getpwent(void); -->
|
||||||
<function name="getpwent">
|
<function name="getpwent">
|
||||||
<use-retval/>
|
|
||||||
<noreturn>false</noreturn>
|
<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>
|
</function>
|
||||||
<!--struct passwd *getpwnam(const char *); -->
|
<!--struct passwd *getpwnam(const char *); -->
|
||||||
<function name="getpwnam">
|
<function name="getpwnam">
|
||||||
<use-retval/>
|
|
||||||
<noreturn>false</noreturn>
|
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</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>
|
</function>
|
||||||
<!-- char *strtok_r(char *str, const char *delim, char **saveptr); -->
|
<!-- char *strtok_r(char *str, const char *delim, char **saveptr); -->
|
||||||
<function name="strtok_r">
|
<function name="strtok_r">
|
||||||
<pure/>
|
<!-- strtok may modify the first argument, so using the return value is not mandatory -->
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
|
<pure/>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
@ -1470,11 +1642,12 @@
|
||||||
</function>
|
</function>
|
||||||
<!-- struct passwd *getpwuid(uid_t uid); -->
|
<!-- struct passwd *getpwuid(uid_t uid); -->
|
||||||
<function name="getpwuid">
|
<function name="getpwuid">
|
||||||
<use-retval/>
|
|
||||||
<noreturn>false</noreturn>
|
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</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>
|
</function>
|
||||||
<!-- int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **); -->
|
<!-- int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **); -->
|
||||||
<function name="getpwuid_r">
|
<function name="getpwuid_r">
|
||||||
|
@ -1672,6 +1845,7 @@
|
||||||
<arg nr="4">
|
<arg nr="4">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="sprintf"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- char *fcvt(double value, int ndigit, int *restrict decpt, int *restrict sign);-->
|
<!-- char *fcvt(double value, int ndigit, int *restrict decpt, int *restrict sign);-->
|
||||||
<!-- LEGACY in POSIX.1-2001, removed in POSIX.1-2008-->
|
<!-- LEGACY in POSIX.1-2001, removed in POSIX.1-2008-->
|
||||||
|
@ -1689,6 +1863,7 @@
|
||||||
<arg nr="4">
|
<arg nr="4">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="sprintf"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- char *gcvt(double value, int ndigit, char *buf);-->
|
<!-- char *gcvt(double value, int ndigit, char *buf);-->
|
||||||
<!-- LEGACY in POSIX.1-2001, removed in POSIX.1-2008-->
|
<!-- LEGACY in POSIX.1-2001, removed in POSIX.1-2008-->
|
||||||
|
@ -1703,6 +1878,7 @@
|
||||||
<arg nr="3">
|
<arg nr="3">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="sprintf"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- off_t lseek(int fildes, off_t offset, int whence); -->
|
<!-- off_t lseek(int fildes, off_t offset, int whence); -->
|
||||||
<function name="lseek">
|
<function name="lseek">
|
||||||
|
@ -1777,22 +1953,42 @@
|
||||||
<function name="unsetenv">
|
<function name="unsetenv">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-null/>
|
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<!-- struct tm *localtime_r(const time_t *timep, struct tm *result); -->
|
<!-- struct tm * localtime(const time_t *tp); -->
|
||||||
<function name="localtime_r">
|
<function name="localtime,std::localtime">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</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">
|
<arg nr="2">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</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); -->
|
<!-- int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); -->
|
||||||
<function name="readdir_r">
|
<function name="readdir_r">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
|
@ -1852,6 +2048,7 @@
|
||||||
<arg nr="2">
|
<arg nr="2">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="strftime"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- char *ctime_r(const time_t *timep, char *buf); -->
|
<!-- char *ctime_r(const time_t *timep, char *buf); -->
|
||||||
<function name="ctime_r">
|
<function name="ctime_r">
|
||||||
|
@ -1864,6 +2061,7 @@
|
||||||
<arg nr="2">
|
<arg nr="2">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" reason="Obsolescent" alternatives="strftime"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- struct tm *gmtime_r(const time_t *timep, struct tm *result); -->
|
<!-- struct tm *gmtime_r(const time_t *timep, struct tm *result); -->
|
||||||
<function name="gmtime_r">
|
<function name="gmtime_r">
|
||||||
|
@ -1877,6 +2075,17 @@
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</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 -->
|
<!-- http://pubs.opengroup.org/onlinepubs/007908799/xsh/time.h.html -->
|
||||||
<!-- int clock_settime(clockid_t clock_id, const struct timespec *tp); -->
|
<!-- int clock_settime(clockid_t clock_id, const struct timespec *tp); -->
|
||||||
<function name="clock_settime">
|
<function name="clock_settime">
|
||||||
|
@ -1926,6 +2135,380 @@
|
||||||
</arg>
|
</arg>
|
||||||
<arg nr="2"/>
|
<arg nr="2"/>
|
||||||
</function>
|
</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>
|
<memory>
|
||||||
<alloc init="true">strdup</alloc>
|
<alloc init="true">strdup</alloc>
|
||||||
<alloc init="true">strndup</alloc>
|
<alloc init="true">strndup</alloc>
|
||||||
|
@ -1956,6 +2539,7 @@
|
||||||
<alloc init="true">popen</alloc>
|
<alloc init="true">popen</alloc>
|
||||||
<dealloc>pclose</dealloc>
|
<dealloc>pclose</dealloc>
|
||||||
</resource>
|
</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_port_t" sign="u" size="2"/>
|
||||||
<podtype name="in_addr_t" sign="u" size="4"/>
|
<podtype name="in_addr_t" sign="u" size="4"/>
|
||||||
<podtype name="socklen_t" sign="u" size="4"/>
|
<podtype name="socklen_t" sign="u" size="4"/>
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
<not-null/>
|
<not-null/>
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
|
<warn severity="style" cstd="c99" alternatives="strftime" reason="Obsolete"/>
|
||||||
</function>
|
</function>
|
||||||
<!-- void assert(int expression) -->
|
<!-- void assert(int expression) -->
|
||||||
<function name="assert">
|
<function name="assert">
|
||||||
|
@ -1435,12 +1436,14 @@
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<!-- char *gets(char *buffer); -->
|
<!-- char *gets(char *buffer); -->
|
||||||
<function name="gets">
|
<function name="gets,std::gets">
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<arg nr="1">
|
<arg nr="1">
|
||||||
<not-null/>
|
<not-null/>
|
||||||
</arg>
|
</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>
|
</function>
|
||||||
<!-- struct tm * gmtime(const time_t *tp); -->
|
<!-- struct tm * gmtime(const time_t *tp); -->
|
||||||
<function name="gmtime,std::gmtime">
|
<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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#ifndef checknonreentrantfunctionsH
|
#ifndef checkfunctionsH
|
||||||
#define checknonreentrantfunctionsH
|
#define checkfunctionsH
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
|
|
||||||
|
|
||||||
/// @addtogroup Checks
|
/// @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:
|
public:
|
||||||
/** This constructor is used when registering the CheckNonReentrantFunctions */
|
/** This constructor is used when registering the CheckFunctions */
|
||||||
CheckNonReentrantFunctions() : Check(myName()) {
|
CheckFunctions() : Check(myName()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This constructor is used when running checks. */
|
/** 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) {
|
: Check(myName(), tokenizer, settings, errorLogger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
||||||
CheckNonReentrantFunctions checkNonReentrantFunctions(tokenizer, settings, errorLogger);
|
CheckFunctions checkFunctions(tokenizer, settings, errorLogger);
|
||||||
checkNonReentrantFunctions.nonReentrantFunctions();
|
checkFunctions.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check for non reentrant functions */
|
/** Check for functions that should not be used */
|
||||||
void nonReentrantFunctions();
|
void check();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||||
|
CheckFunctions c(0, settings, errorLogger);
|
||||||
|
|
||||||
static std::string generateErrorMessage(const std::string& function);
|
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);
|
||||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const;
|
}
|
||||||
|
|
||||||
static std::string myName() {
|
|
||||||
return "Non reentrant functions";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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="checkbufferoverrun.cpp" />
|
||||||
<ClCompile Include="checkclass.cpp" />
|
<ClCompile Include="checkclass.cpp" />
|
||||||
<ClCompile Include="checkcondition.cpp" />
|
<ClCompile Include="checkcondition.cpp" />
|
||||||
|
<ClCompile Include="checkfunctions.cpp" />
|
||||||
<ClCompile Include="checkstring.cpp" />
|
<ClCompile Include="checkstring.cpp" />
|
||||||
<ClCompile Include="checkexceptionsafety.cpp" />
|
<ClCompile Include="checkexceptionsafety.cpp" />
|
||||||
<ClCompile Include="checkinternal.cpp" />
|
<ClCompile Include="checkinternal.cpp" />
|
||||||
<ClCompile Include="checkio.cpp" />
|
<ClCompile Include="checkio.cpp" />
|
||||||
<ClCompile Include="checkleakautovar.cpp" />
|
<ClCompile Include="checkleakautovar.cpp" />
|
||||||
<ClCompile Include="checkmemoryleak.cpp" />
|
<ClCompile Include="checkmemoryleak.cpp" />
|
||||||
<ClCompile Include="checknonreentrantfunctions.cpp" />
|
|
||||||
<ClCompile Include="checknullpointer.cpp" />
|
<ClCompile Include="checknullpointer.cpp" />
|
||||||
<ClCompile Include="checkobsolescentfunctions.cpp" />
|
|
||||||
<ClCompile Include="checkother.cpp" />
|
<ClCompile Include="checkother.cpp" />
|
||||||
<ClCompile Include="checkpostfixoperator.cpp" />
|
<ClCompile Include="checkpostfixoperator.cpp" />
|
||||||
<ClCompile Include="checksizeof.cpp" />
|
<ClCompile Include="checksizeof.cpp" />
|
||||||
|
@ -101,15 +100,14 @@
|
||||||
<ClInclude Include="checkbufferoverrun.h" />
|
<ClInclude Include="checkbufferoverrun.h" />
|
||||||
<ClInclude Include="checkclass.h" />
|
<ClInclude Include="checkclass.h" />
|
||||||
<ClInclude Include="checkcondition.h" />
|
<ClInclude Include="checkcondition.h" />
|
||||||
|
<ClInclude Include="checkfunctions.h" />
|
||||||
<ClInclude Include="checkstring.h" />
|
<ClInclude Include="checkstring.h" />
|
||||||
<ClInclude Include="checkexceptionsafety.h" />
|
<ClInclude Include="checkexceptionsafety.h" />
|
||||||
<ClInclude Include="checkinternal.h" />
|
<ClInclude Include="checkinternal.h" />
|
||||||
<ClInclude Include="checkio.h" />
|
<ClInclude Include="checkio.h" />
|
||||||
<ClInclude Include="checkleakautovar.h" />
|
<ClInclude Include="checkleakautovar.h" />
|
||||||
<ClInclude Include="checkmemoryleak.h" />
|
<ClInclude Include="checkmemoryleak.h" />
|
||||||
<ClInclude Include="checknonreentrantfunctions.h" />
|
|
||||||
<ClInclude Include="checknullpointer.h" />
|
<ClInclude Include="checknullpointer.h" />
|
||||||
<ClInclude Include="checkobsolescentfunctions.h" />
|
|
||||||
<ClInclude Include="checkother.h" />
|
<ClInclude Include="checkother.h" />
|
||||||
<ClInclude Include="checkpostfixoperator.h" />
|
<ClInclude Include="checkpostfixoperator.h" />
|
||||||
<ClInclude Include="checksizeof.h" />
|
<ClInclude Include="checksizeof.h" />
|
||||||
|
|
|
@ -32,15 +32,9 @@
|
||||||
<ClCompile Include="checkmemoryleak.cpp">
|
<ClCompile Include="checkmemoryleak.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="checknonreentrantfunctions.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="checknullpointer.cpp">
|
<ClCompile Include="checknullpointer.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="checkobsolescentfunctions.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="checkother.cpp">
|
<ClCompile Include="checkother.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -143,6 +137,9 @@
|
||||||
<ClCompile Include="astutils.cpp">
|
<ClCompile Include="astutils.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="checkfunctions.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="checkbufferoverrun.h">
|
<ClInclude Include="checkbufferoverrun.h">
|
||||||
|
@ -157,15 +154,9 @@
|
||||||
<ClInclude Include="checkmemoryleak.h">
|
<ClInclude Include="checkmemoryleak.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="checknonreentrantfunctions.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="checknullpointer.h">
|
<ClInclude Include="checknullpointer.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="checkobsolescentfunctions.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="checkother.h">
|
<ClInclude Include="checkother.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -286,6 +277,9 @@
|
||||||
<ClInclude Include="utils.h">
|
<ClInclude Include="utils.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="checkfunctions.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="version.rc" />
|
<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* scan = functionnode->FindAttribute("scan");
|
||||||
const tinyxml2::XMLAttribute* secure = functionnode->FindAttribute("secure");
|
const tinyxml2::XMLAttribute* secure = functionnode->FindAttribute("secure");
|
||||||
_formatstr[name] = std::make_pair(scan && scan->BoolValue(), secure && secure->BoolValue());
|
_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
|
} else
|
||||||
unknown_elements.insert(functionnodename);
|
unknown_elements.insert(functionnodename);
|
||||||
}
|
}
|
||||||
|
@ -852,6 +892,16 @@ bool Library::isNotLibraryFunction(const Token *ftok) const
|
||||||
return args != callargs;
|
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
|
bool Library::isUseRetVal(const Token* ftok) const
|
||||||
{
|
{
|
||||||
return (!isNotLibraryFunction(ftok) &&
|
return (!isNotLibraryFunction(ftok) &&
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "mathlib.h"
|
#include "mathlib.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
#include "standards.h"
|
||||||
|
#include "errorlogger.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -120,6 +122,15 @@ public:
|
||||||
std::set<std::string> functionconst;
|
std::set<std::string> functionconst;
|
||||||
std::set<std::string> functionpure;
|
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
|
// returns true if ftok is not a library function
|
||||||
bool isNotLibraryFunction(const Token *ftok) const;
|
bool isNotLibraryFunction(const Token *ftok) const;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,33 @@ struct Standards {
|
||||||
|
|
||||||
/** This constructor clear all the variables **/
|
/** This constructor clear all the variables **/
|
||||||
Standards() : c(C11), cpp(CPP11), posix(false) {}
|
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 "tokenize.h"
|
||||||
#include "checkobsolescentfunctions.h"
|
#include "checkfunctions.h"
|
||||||
#include "testsuite.h"
|
#include "testsuite.h"
|
||||||
|
|
||||||
|
|
||||||
class TestObsoleteFunctions : public TestFixture {
|
class TestFunctions : public TestFixture {
|
||||||
public:
|
public:
|
||||||
TestObsoleteFunctions() : TestFixture("TestObsoleteFunctions") {
|
TestFunctions() : TestFixture("TestFunctions") {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -31,8 +31,13 @@ private:
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
settings.addEnabled("style");
|
settings.addEnabled("style");
|
||||||
|
settings.addEnabled("warning");
|
||||||
|
settings.addEnabled("portability");
|
||||||
settings.standards.posix = true;
|
settings.standards.posix = true;
|
||||||
settings.standards.c = Standards::C11;
|
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(testbsd_signal);
|
||||||
TEST_CASE(testgethostbyname);
|
TEST_CASE(testgethostbyname);
|
||||||
|
@ -65,8 +70,9 @@ private:
|
||||||
// function with body
|
// function with body
|
||||||
TEST_CASE(test_function_with_body);
|
TEST_CASE(test_function_with_body);
|
||||||
|
|
||||||
// null pointer dereference in obsoleteFunctions
|
// Non-reentrant functions
|
||||||
TEST_CASE(ticket3238);
|
TEST_CASE(test_crypt);
|
||||||
|
TEST_CASE(test_namespace_handling);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check(const char code[], const char filename[]="test.cpp") {
|
void check(const char code[], const char filename[]="test.cpp") {
|
||||||
|
@ -79,9 +85,9 @@ private:
|
||||||
tokenizer.tokenize(istr, filename);
|
tokenizer.tokenize(istr, filename);
|
||||||
tokenizer.simplifyTokenList2();
|
tokenizer.simplifyTokenList2();
|
||||||
|
|
||||||
// Check for obsolete functions..
|
// Check...
|
||||||
CheckObsoleteFunctions checkObsoleteFunctions(&tokenizer, &settings, this);
|
CheckFunctions checkFunctions(&tokenizer, &settings, this);
|
||||||
checkObsoleteFunctions.obsoleteFunctions();
|
checkFunctions.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void testbsd_signal() {
|
void testbsd_signal() {
|
||||||
|
@ -89,7 +95,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" bsd_signal(SIGABRT, SIG_IGN);\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"
|
check("int f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -108,7 +114,7 @@ private:
|
||||||
" exit(1);\n"
|
" exit(1);\n"
|
||||||
" }\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() {
|
void testgethostbyaddr() {
|
||||||
|
@ -120,7 +126,7 @@ private:
|
||||||
" exit(1);\n"
|
" exit(1);\n"
|
||||||
" }\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() {
|
void testusleep() {
|
||||||
|
@ -128,7 +134,7 @@ private:
|
||||||
"{\n"
|
"{\n"
|
||||||
" usleep( 1000 );\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() {
|
void testindex() {
|
||||||
|
@ -168,7 +174,7 @@ private:
|
||||||
" const char i = index(var, 0);\n"
|
" const char i = index(var, 0);\n"
|
||||||
" return i;\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());
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +182,7 @@ private:
|
||||||
check("void TDataModel::forceRowRefresh(int row) {\n"
|
check("void TDataModel::forceRowRefresh(int row) {\n"
|
||||||
" emit dataChanged(index(row, 0), index(row, columnCount() - 1));\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() {
|
void testrindex() {
|
||||||
|
@ -191,7 +197,7 @@ private:
|
||||||
" const char var[7] = \"rindex\";\n"
|
" const char var[7] = \"rindex\";\n"
|
||||||
" print(rindex(var, 0));\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() {
|
void testgets() {
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\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"
|
check("void f()\n"
|
||||||
"{\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() {
|
void testalloca() {
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *x = alloca(10);\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());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" char *x = alloca(10);\n"
|
" char *x = alloca(10);\n"
|
||||||
"}\n", "test.c");
|
"}", "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());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
settings.standards.c = Standards::C11;
|
||||||
|
settings.standards.cpp = Standards::CPP11;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ticket #3121
|
// ticket #3121
|
||||||
|
@ -253,8 +275,8 @@ private:
|
||||||
" char *x = std::gets(str);\n"
|
" char *x = std::gets(str);\n"
|
||||||
" char *y = 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"
|
ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n"
|
||||||
"[test.cpp:4]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n", errout.str());
|
"[test.cpp:4]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' instead.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiple use
|
// multiple use
|
||||||
|
@ -264,8 +286,8 @@ private:
|
||||||
" char *x = std::gets(str);\n"
|
" char *x = std::gets(str);\n"
|
||||||
" usleep( 1000 );\n"
|
" usleep( 1000 );\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead.\n"
|
ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use '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());
|
"[test.cpp:4]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_c_declaration() {
|
void test_c_declaration() {
|
||||||
|
@ -275,14 +297,14 @@ private:
|
||||||
" char s [ 10 ] ;\n"
|
" char s [ 10 ] ;\n"
|
||||||
" gets ( s ) ;\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"
|
check("int getcontext(ucontext_t *ucp);\n"
|
||||||
"int f (ucontext_t *ucp)\n"
|
"int f (ucontext_t *ucp)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" getcontext ( ucp ) ;\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() {
|
void test_function_with_body() {
|
||||||
|
@ -295,11 +317,81 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ticket3238() {
|
void test_crypt() {
|
||||||
check("__FBSDID(\"...\");\n");
|
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());
|
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(garbageCode155); // #7118
|
||||||
TEST_CASE(garbageCode156); // #7120
|
TEST_CASE(garbageCode156); // #7120
|
||||||
TEST_CASE(garbageCode157); // #7131
|
TEST_CASE(garbageCode157); // #7131
|
||||||
|
TEST_CASE(garbageCode158); // #3238
|
||||||
|
|
||||||
TEST_CASE(garbageValueFlow);
|
TEST_CASE(garbageValueFlow);
|
||||||
TEST_CASE(garbageSymbolDatabase);
|
TEST_CASE(garbageSymbolDatabase);
|
||||||
|
@ -1241,6 +1242,11 @@ private:
|
||||||
"template std::swap\n"), InternalError);
|
"template std::swap\n"), InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void garbageCode158() { // #3238
|
||||||
|
checkCode("__FBSDID(\"...\");\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void garbageValueFlow() {
|
void garbageValueFlow() {
|
||||||
// #6089
|
// #6089
|
||||||
const char* code = "{} int foo(struct, x1, struct x2, x3, int, x5, x6, x7)\n"
|
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_valid);
|
||||||
TEST_CASE(function_arg_minsize);
|
TEST_CASE(function_arg_minsize);
|
||||||
TEST_CASE(function_namespace);
|
TEST_CASE(function_namespace);
|
||||||
|
TEST_CASE(function_warn);
|
||||||
TEST_CASE(memory);
|
TEST_CASE(memory);
|
||||||
TEST_CASE(memory2); // define extra "free" allocation functions
|
TEST_CASE(memory2); // define extra "free" allocation functions
|
||||||
TEST_CASE(resource);
|
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 {
|
void memory() const {
|
||||||
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
|
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
|
||||||
"<def>\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="testlibrary.cpp" />
|
||||||
<ClCompile Include="testmathlib.cpp" />
|
<ClCompile Include="testmathlib.cpp" />
|
||||||
<ClCompile Include="testmemleak.cpp" />
|
<ClCompile Include="testmemleak.cpp" />
|
||||||
<ClCompile Include="testnonreentrantfunctions.cpp" />
|
|
||||||
<ClCompile Include="testnullpointer.cpp" />
|
<ClCompile Include="testnullpointer.cpp" />
|
||||||
<ClCompile Include="testobsolescentfunctions.cpp" />
|
<ClCompile Include="testfunctions.cpp" />
|
||||||
<ClCompile Include="testoptions.cpp" />
|
<ClCompile Include="testoptions.cpp" />
|
||||||
<ClCompile Include="testother.cpp" />
|
<ClCompile Include="testother.cpp" />
|
||||||
<ClCompile Include="testpath.cpp" />
|
<ClCompile Include="testpath.cpp" />
|
||||||
|
|
|
@ -64,15 +64,9 @@
|
||||||
<ClCompile Include="testmemleak.cpp">
|
<ClCompile Include="testmemleak.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="testnonreentrantfunctions.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="testnullpointer.cpp">
|
<ClCompile Include="testnullpointer.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="testobsolescentfunctions.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="testoptions.cpp">
|
<ClCompile Include="testoptions.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -205,6 +199,9 @@
|
||||||
<ClCompile Include="testtokenlist.cpp">
|
<ClCompile Include="testtokenlist.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="testfunctions.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="options.h">
|
<ClInclude Include="options.h">
|
||||||
|
|
Loading…
Reference in New Issue