Merge pull request #807 from siemens/expand-y2038-checker

Update Y2038 addon
This commit is contained in:
Daniel Marjamäki 2016-06-29 11:57:50 +02:00 committed by GitHub
commit 0630a02523
7 changed files with 138 additions and 22 deletions

View File

@ -39,14 +39,14 @@ There is Y2038-proofing work in progress on the Linux and GNU glibc front.
2. What is the Y2038 ccpcheck addon? 2. What is the Y2038 ccpcheck addon?
The Y2038 cppcheck addon is a tool to help detect code which might need fixing The Y2038 cppcheck addon is a tool to help detect code which might need fixing
because it is Y2038-sensitive. This may be because it uses types or functions because it is Y2038-unsafe. This may be because it uses types or functions from
from libc or from the Linux kernel which are known not to be Y2038-proof. GNU libc or from the Linux kernel which are known not to be Y2038-proof.
3. How does the Y2038 cppcheck addon work? 3. How does the Y2038 cppcheck addon work?
The Y2038 cppcheck addon takes XML dumps produced by cppcheck from source code The Y2038 cppcheck addon takes XML dumps produced by cppcheck from source code
files and looks for the names of types or functions which are known to be Y2038- files and looks for the names of types or functions which are known to be Y2038-
sensitive, and emits diagnostics whenever it finds one. unsafe, and emits diagnostics whenever it finds one.
Of course, this is of little use if your code uses a Y2038-proof glibc and Of course, this is of little use if your code uses a Y2038-proof glibc and
correctly configured Y2038-proof time support. correctly configured Y2038-proof time support.
@ -85,10 +85,10 @@ The Y2038 cppcheck performs the following checks:
which defaults to 32-bit time support. which defaults to 32-bit time support.
3. Upon meeting a symbol (type or function) which is known to be Y2038- 3. Upon meeting a symbol (type or function) which is known to be Y2038-
sensitive, if _USE_TIME_BITS64 is undefined or _TIME_BITS not properly unsafe, if _USE_TIME_BITS64 is undefined or _TIME_BITS not properly
defined, this warning diagnostic is emitted: defined, this warning diagnostic is emitted:
Warning: <symbol> might be Y2038-sensitive Warning: <symbol> is Y2038-unsafe
This reflects the fact that the user code is referring to a symbol This reflects the fact that the user code is referring to a symbol
which, when glibc defaults to 32-bit time support, might fail Y2038. which, when glibc defaults to 32-bit time support, might fail Y2038.
@ -143,8 +143,8 @@ Checking addons/y2038/test/y2038-test-4-good.c.dump, config ""...
[addons/y2038/test/y2038-test-1-bad-time-bits.c:10]: (information) addons/y2038/test/y2038-inc.h was included from here [addons/y2038/test/y2038-test-1-bad-time-bits.c:10]: (information) addons/y2038/test/y2038-inc.h was included from here
[addons/y2038/test/y2038-inc.h:9]: (warning) _USE_TIME_BITS64 is defined but _TIME_BITS was not [addons/y2038/test/y2038-inc.h:9]: (warning) _USE_TIME_BITS64 is defined but _TIME_BITS was not
[addons/y2038/test/y2038-test-2-no-time-bits.c:8]: (information) addons/y2038/test/y2038-inc.h was included from here [addons/y2038/test/y2038-test-2-no-time-bits.c:8]: (information) addons/y2038/test/y2038-inc.h was included from here
[addons/y2038/test/y2038-test-3-no-use-time-bits.c:13]: (warning) timespec might be Y2038-sensitive [addons/y2038/test/y2038-test-3-no-use-time-bits.c:13]: (warning) timespec is Y2038-unsafe
[addons/y2038/test/y2038-test-3-no-use-time-bits.c:15]: (warning) clock_gettime might be Y2038-sensitive [addons/y2038/test/y2038-test-3-no-use-time-bits.c:15]: (warning) clock_gettime is Y2038-unsafe
Note: y2038.py recognizes option --template as cppcheck does, including Note: y2038.py recognizes option --template as cppcheck does, including
pre-defined templates 'gcc', 'vs' and 'edit'. The short form -t is also pre-defined templates 'gcc', 'vs' and 'edit'. The short form -t is also

View File

@ -8,4 +8,24 @@
#define _USE_TIME_BITS64 #define _USE_TIME_BITS64
/*
* Declare just enough for clock_gettime
*/
typedef int clockid_t;
typedef int __time_t;
typedef long int __syscall_slong_t;
struct timespec
{
__time_t tv_sec; /* Seconds. */
__syscall_slong_t tv_nsec; /* Nanoseconds. */
};
extern int clock_gettime(clockid_t clk_id, struct timespec *tp);
#define CLOCK_REALTIME 0
#endif /* INC2038 */ #endif /* INC2038 */

View File

@ -11,7 +11,7 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
clockid_t my_clk_id; clockid_t my_clk_id = CLOCK_REALTIME;
struct timespec *my_tp; struct timespec *my_tp;
return clock_gettime(my_clk_id, &my_tp); return clock_gettime(my_clk_id, &my_tp);

View File

@ -9,7 +9,7 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
clockid_t my_clk_id; clockid_t my_clk_id = CLOCK_REALTIME;
struct timespec *my_tp; struct timespec *my_tp;
return clock_gettime(my_clk_id, &my_tp); return clock_gettime(my_clk_id, &my_tp);

View File

@ -9,7 +9,7 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
clockid_t my_clk_id; clockid_t my_clk_id = CLOCK_REALTIME;
struct timespec *my_tp; struct timespec *my_tp;
return clock_gettime(my_clk_id, &my_tp); return clock_gettime(my_clk_id, &my_tp);

View File

@ -8,7 +8,7 @@
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
clockid_t my_clk_id; clockid_t my_clk_id = CLOCK_REALTIME;
struct timespec *my_tp; struct timespec *my_tp;
return clock_gettime(my_clk_id, &my_tp); return clock_gettime(my_clk_id, &my_tp);

View File

@ -6,7 +6,7 @@
# #
# 1. _TIME_BITS being defined to something else than 64 bits # 1. _TIME_BITS being defined to something else than 64 bits
# 2. _USE_TIME_BITS64 being defined when _TIME_BITS is not # 2. _USE_TIME_BITS64 being defined when _TIME_BITS is not
# 3. Any Y2038-sensitive symbol when _USE_TIME_BITS64 is not defined. # 3. Any Y2038-unsafe symbol when _USE_TIME_BITS64 is not defined.
# #
# Example usage: # Example usage:
# $ cppcheck --dump path-to-src/ # $ cppcheck --dump path-to-src/
@ -77,17 +77,113 @@ re_define_use_time_bits64 = re.compile(r'^\s*#\s*define\s+_USE_TIME_BITS64\s*$')
# test for '#undef _USE_TIME_BITS64' (if it ever happens) # test for '#undef _USE_TIME_BITS64' (if it ever happens)
re_undef_use_time_bits64 = re.compile(r'^\s*#\s*undef\s+_USE_TIME_BITS64\s*$') re_undef_use_time_bits64 = re.compile(r'^\s*#\s*undef\s+_USE_TIME_BITS64\s*$')
#------------------------------------ #---------------------------------
# List of Y2038-sensitive identifiers # List of Y2038-unsafe identifiers
#------------------------------------ #---------------------------------
# This is WIP. Eventually it should contain all identifiers (types # This is WIP. Eventually it should contain all identifiers (types
# and functions) which would be affected by the Y2038 bug. # and functions) which would be affected by the Y2038 bug.
id_Y2038 = [ id_Y2038 = [
'time_t', # Y2038-unsafe types by definition
'time_t'
# Types using Y2038-unsafe types
'lastlog',
'msqid_ds',
'semid_ds',
'timeb',
'timespec', 'timespec',
'clock_gettime' 'timeval',
'utimbuf',
'itimerspec',
'stat',
'clnt_ops',
'elf_prstatus',
'itimerval',
'ntptimeval',
'rusage',
'timex',
'utmp',
'utmpx',
# APIs using 2038-unsafe types
'ctime',
'ctime_r',
'difftime',
'gmtime',
'gmtime_r',
'localtime',
'localtime_r',
'mktime',
'stime',
'timegm',
'timelocal',
'time',
'msgctl',
'ftime',
'aio_suspend',
'clock_getres',
'clock_gettime',
'clock_nanosleep',
'clock_settime',
'futimens',
'mq_timedreceive',
'mq_timedsend',
'nanosleep',
'pselect',
'pthread_cond_timedwait',
'pthread_mutex_timedlock',
'pthread_rwlock_timedrdlock',
'pthread_rwlock_timedwrlock',
'sched_rr_get_interval',
'sem_timedwait',
'sigtimedwait',
'timespec_get',
'utimensat',
'adjtime',
'pmap_rmtcall',
'clntudp_bufcreate',
'clntudp_create',
'futimes',
'gettimeofday',
'lutimes',
'select',
'settimeofday',
'utimes',
'utime',
'timerfd_gettime',
'timerfd_settime',
'timer_gettime',
'timer_settime',
'fstatat',
'fstat',
'__fxstatat',
'__fxstat',
'lstat',
'__lxstat',
'stat',
'__xstat',
'struct itimerval',
'setitimer',
'getitimer',
'ntp_gettime',
'getrusage',
'wait3',
'wait4',
'adjtimex',
'ntp_adjtime',
'getutent_r',
'getutent',
'getutid_r',
'getutid',
'getutline_r',
'getutline',
'login',
'pututline',
'updwtmp',
'getutxent',
'getutxid',
'getutxline',
'pututxline'
] ]
# return all files ending in .dump among or under the given paths # return all files ending in .dump among or under the given paths
@ -182,7 +278,7 @@ for dumpfile in dumpfiles:
if not any(lower <= int(token.linenr) <= upper if not any(lower <= int(token.linenr) <= upper
for (lower, upper) in safe_ranges): for (lower, upper) in safe_ranges):
reportTokDiag(args.template, cfg, token, 'warning', reportTokDiag(args.template, cfg, token, 'warning',
token.str + ' might be Y2038-sensitive') token.str + ' is Y2038-unsafe')
token = token.next token = token.next
printDiagnostics() printDiagnostics()