cppcheck-py 2.9__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. cppcheck/__init__.py +55 -0
  2. cppcheck/cppcheck-2.9.tar.gz +0 -0
  3. cppcheck/data/addons/__init__.py +0 -0
  4. cppcheck/data/addons/cppcheck.py +39 -0
  5. cppcheck/data/addons/cppcheckdata.py +1529 -0
  6. cppcheck/data/addons/findcasts.py +33 -0
  7. cppcheck/data/addons/misc.py +163 -0
  8. cppcheck/data/addons/misra.py +4728 -0
  9. cppcheck/data/addons/misra_9.py +513 -0
  10. cppcheck/data/addons/naming.py +91 -0
  11. cppcheck/data/addons/namingng.py +253 -0
  12. cppcheck/data/addons/runaddon.py +12 -0
  13. cppcheck/data/addons/threadsafety.py +39 -0
  14. cppcheck/data/addons/y2038.py +252 -0
  15. cppcheck/data/cfg/avr.cfg +431 -0
  16. cppcheck/data/cfg/bento4.cfg +142 -0
  17. cppcheck/data/cfg/boost.cfg +1268 -0
  18. cppcheck/data/cfg/bsd.cfg +546 -0
  19. cppcheck/data/cfg/cairo.cfg +88 -0
  20. cppcheck/data/cfg/cppcheck-lib.cfg +72 -0
  21. cppcheck/data/cfg/cppunit.cfg +48 -0
  22. cppcheck/data/cfg/daca.cfg +31 -0
  23. cppcheck/data/cfg/dpdk.cfg +11 -0
  24. cppcheck/data/cfg/embedded_sql.cfg +4 -0
  25. cppcheck/data/cfg/emscripten.cfg +7 -0
  26. cppcheck/data/cfg/ginac.cfg +12848 -0
  27. cppcheck/data/cfg/gnu.cfg +1626 -0
  28. cppcheck/data/cfg/googletest.cfg +60 -0
  29. cppcheck/data/cfg/gtk.cfg +20584 -0
  30. cppcheck/data/cfg/icu.cfg +6 -0
  31. cppcheck/data/cfg/kde.cfg +51 -0
  32. cppcheck/data/cfg/libcerror.cfg +128 -0
  33. cppcheck/data/cfg/libcurl.cfg +487 -0
  34. cppcheck/data/cfg/libsigc++.cfg +36 -0
  35. cppcheck/data/cfg/lua.cfg +316 -0
  36. cppcheck/data/cfg/mfc.cfg +256 -0
  37. cppcheck/data/cfg/microsoft_atl.cfg +40 -0
  38. cppcheck/data/cfg/microsoft_sal.cfg +491 -0
  39. cppcheck/data/cfg/microsoft_unittest.cfg +20 -0
  40. cppcheck/data/cfg/motif.cfg +318 -0
  41. cppcheck/data/cfg/nspr.cfg +38 -0
  42. cppcheck/data/cfg/ntl.cfg +6907 -0
  43. cppcheck/data/cfg/opencv2.cfg +132 -0
  44. cppcheck/data/cfg/opengl.cfg +580 -0
  45. cppcheck/data/cfg/openmp.cfg +157 -0
  46. cppcheck/data/cfg/openssl.cfg +174 -0
  47. cppcheck/data/cfg/pcre.cfg +165 -0
  48. cppcheck/data/cfg/posix.cfg +6252 -0
  49. cppcheck/data/cfg/python.cfg +674 -0
  50. cppcheck/data/cfg/qt.cfg +5255 -0
  51. cppcheck/data/cfg/ruby.cfg +142 -0
  52. cppcheck/data/cfg/sdl.cfg +354 -0
  53. cppcheck/data/cfg/sfml.cfg +301 -0
  54. cppcheck/data/cfg/sqlite3.cfg +1527 -0
  55. cppcheck/data/cfg/std.cfg +8716 -0
  56. cppcheck/data/cfg/tinyxml2.cfg +56 -0
  57. cppcheck/data/cfg/vcl.cfg +4 -0
  58. cppcheck/data/cfg/windows.cfg +17941 -0
  59. cppcheck/data/cfg/wxsqlite3.cfg +1955 -0
  60. cppcheck/data/cfg/wxsvg.cfg +16905 -0
  61. cppcheck/data/cfg/wxwidgets.cfg +16464 -0
  62. cppcheck/data/cfg/zlib.cfg +1450 -0
  63. cppcheck/data/cppcheck-htmlreport +986 -0
  64. cppcheck/data/cppcheck.exe +0 -0
  65. cppcheck/data/platforms/aix_ppc64.xml +17 -0
  66. cppcheck/data/platforms/arm32-wchar_t2.xml +17 -0
  67. cppcheck/data/platforms/arm32-wchar_t4.xml +17 -0
  68. cppcheck/data/platforms/arm64-wchar_t2.xml +17 -0
  69. cppcheck/data/platforms/arm64-wchar_t4.xml +17 -0
  70. cppcheck/data/platforms/avr8.xml +18 -0
  71. cppcheck/data/platforms/cray_sv1.xml +17 -0
  72. cppcheck/data/platforms/elbrus-e1cp.xml +18 -0
  73. cppcheck/data/platforms/mips32.xml +18 -0
  74. cppcheck/data/platforms/msp430_eabi_large_datamodel.xml +17 -0
  75. cppcheck/data/platforms/pic16.xml +18 -0
  76. cppcheck/data/platforms/pic8-enhanced.xml +18 -0
  77. cppcheck/data/platforms/pic8.xml +18 -0
  78. cppcheck/data/platforms/unix32-unsigned.xml +17 -0
  79. cppcheck/data/platforms/unix64-unsigned.xml +17 -0
  80. cppcheck_py-2.9.dist-info/METADATA +76 -0
  81. cppcheck_py-2.9.dist-info/RECORD +84 -0
  82. cppcheck_py-2.9.dist-info/WHEEL +5 -0
  83. cppcheck_py-2.9.dist-info/entry_points.txt +4 -0
  84. cppcheck_py-2.9.dist-info/licenses/LICENSE.md +191 -0
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # cppcheck addon for naming conventions
4
+ # An enhanced version. Configuration is taken from a json file
5
+ # It supports to check for type-based prefixes in function or variable names.
6
+ #
7
+ # Example usage (variable name must start with lowercase, function name must start with uppercase):
8
+ # $ cppcheck --dump path-to-src/
9
+ # $ python namingng.py test.c.dump
10
+ #
11
+ # JSON format:
12
+ #
13
+ # {
14
+ # "RE_VARNAME": "[a-z]*[a-zA-Z0-9_]*\\Z",
15
+ # "RE_PRIVATE_MEMBER_VARIABLE": null,
16
+ # "RE_FUNCTIONNAME": "[a-z0-9A-Z]*\\Z",
17
+ # "var_prefixes": {"uint32_t": "ui32"},
18
+ # "function_prefixes": {"uint16_t": "ui16",
19
+ # "uint32_t": "ui32"}
20
+ # }
21
+ #
22
+ # RE_VARNAME, RE_PRIVATE_MEMBER_VARIABLE and RE_FUNCTIONNAME are regular expressions to cover the basic names
23
+ # In var_prefixes and function_prefixes there are the variable-type/prefix pairs
24
+
25
+ import cppcheckdata
26
+ import sys
27
+ import re
28
+ import argparse
29
+ import json
30
+
31
+
32
+ # Auxiliary class
33
+ class DataStruct:
34
+ def __init__(self, file, linenr, string):
35
+ self.file = file
36
+ self.linenr = linenr
37
+ self.str = string
38
+
39
+
40
+ def reportError(filename, linenr, severity, msg):
41
+ message = "[{filename}:{linenr}] ( {severity} ) naming.py: {msg}\n".format(
42
+ filename=filename,
43
+ linenr=linenr,
44
+ severity=severity,
45
+ msg=msg
46
+ )
47
+ sys.stderr.write(message)
48
+ return message
49
+
50
+
51
+ def loadConfig(configfile):
52
+ with open(configfile) as fh:
53
+ data = json.load(fh)
54
+ return data
55
+
56
+
57
+ def checkTrueRegex(data, expr, msg, errors):
58
+ res = re.match(expr, data.str)
59
+ if res:
60
+ errors.append(reportError(data.file, data.linenr, 'style', msg))
61
+
62
+
63
+ def checkFalseRegex(data, expr, msg, errors):
64
+ res = re.match(expr, data.str)
65
+ if not res:
66
+ errors.append(reportError(data.file, data.linenr, 'style', msg))
67
+
68
+
69
+ def evalExpr(conf, exp, mockToken, msgType, errors):
70
+ if isinstance(conf, dict):
71
+ if conf[exp][0]:
72
+ msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
73
+ checkTrueRegex(mockToken, exp, msg, errors)
74
+ elif ~conf[exp][0]:
75
+ msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][1]
76
+ checkFalseRegex(mockToken, exp, msg, errors)
77
+ else:
78
+ msg = msgType + ' ' + mockToken.str + ' violates naming convention : ' + conf[exp][0]
79
+ checkFalseRegex(mockToken, exp, msg, errors)
80
+ else:
81
+ msg = msgType + ' ' + mockToken.str + ' violates naming convention'
82
+ checkFalseRegex(mockToken, exp, msg, errors)
83
+
84
+
85
+ def process(dumpfiles, configfile, debugprint=False):
86
+
87
+ errors = []
88
+
89
+ conf = loadConfig(configfile)
90
+
91
+ for afile in dumpfiles:
92
+ if not afile[-5:] == '.dump':
93
+ continue
94
+ print('Checking ' + afile + '...')
95
+ data = cppcheckdata.CppcheckData(afile)
96
+
97
+ # Check File naming
98
+ if "RE_FILE" in conf and conf["RE_FILE"]:
99
+ mockToken = DataStruct(afile[:-5], "0", afile[afile.rfind('/') + 1:-5])
100
+ msgType = 'File name'
101
+ for exp in conf["RE_FILE"]:
102
+ evalExpr(conf["RE_FILE"], exp, mockToken, msgType, errors)
103
+
104
+ # Check Namespace naming
105
+ if "RE_NAMESPACE" in conf and conf["RE_NAMESPACE"]:
106
+ for tk in data.rawTokens:
107
+ if tk.str == 'namespace':
108
+ mockToken = DataStruct(tk.next.file, tk.next.linenr, tk.next.str)
109
+ msgType = 'Namespace'
110
+ for exp in conf["RE_NAMESPACE"]:
111
+ evalExpr(conf["RE_NAMESPACE"], exp, mockToken, msgType, errors)
112
+
113
+ for cfg in data.configurations:
114
+ print('Checking %s, config %s...' % (afile, cfg.name))
115
+ if "RE_VARNAME" in conf and conf["RE_VARNAME"]:
116
+ for var in cfg.variables:
117
+ if var.nameToken and var.access != 'Global' and var.access != 'Public' and var.access != 'Private':
118
+ prev = var.nameToken.previous
119
+ varType = prev.str
120
+ while "*" in varType and len(varType.replace("*", "")) == 0:
121
+ prev = prev.previous
122
+ varType = prev.str + varType
123
+
124
+ if debugprint:
125
+ print("Variable Name: " + str(var.nameToken.str))
126
+ print("original Type Name: " + str(var.nameToken.valueType.originalTypeName))
127
+ print("Type Name: " + var.nameToken.valueType.type)
128
+ print("Sign: " + str(var.nameToken.valueType.sign))
129
+ print("variable type: " + varType)
130
+ print("\n")
131
+ print("\t-- {} {}".format(varType, str(var.nameToken.str)))
132
+
133
+ if conf["skip_one_char_variables"] and len(var.nameToken.str) == 1:
134
+ continue
135
+ if varType in conf["var_prefixes"]:
136
+ if not var.nameToken.str.startswith(conf["var_prefixes"][varType]):
137
+ errors.append(reportError(
138
+ var.typeStartToken.file,
139
+ var.typeStartToken.linenr,
140
+ 'style',
141
+ 'Variable ' +
142
+ var.nameToken.str +
143
+ ' violates naming convention'))
144
+
145
+ mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
146
+ msgType = 'Variable'
147
+ for exp in conf["RE_VARNAME"]:
148
+ evalExpr(conf["RE_VARNAME"], exp, mockToken, msgType, errors)
149
+
150
+ # Check Private Variable naming
151
+ if "RE_PRIVATE_MEMBER_VARIABLE" in conf and conf["RE_PRIVATE_MEMBER_VARIABLE"]:
152
+ # TODO: Not converted yet
153
+ for var in cfg.variables:
154
+ if (var.access is None) or var.access != 'Private':
155
+ continue
156
+ mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
157
+ msgType = 'Private member variable'
158
+ for exp in conf["RE_PRIVATE_MEMBER_VARIABLE"]:
159
+ evalExpr(conf["RE_PRIVATE_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
160
+
161
+ # Check Public Member Variable naming
162
+ if "RE_PUBLIC_MEMBER_VARIABLE" in conf and conf["RE_PUBLIC_MEMBER_VARIABLE"]:
163
+ for var in cfg.variables:
164
+ if (var.access is None) or var.access != 'Public':
165
+ continue
166
+ mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
167
+ msgType = 'Public member variable'
168
+ for exp in conf["RE_PUBLIC_MEMBER_VARIABLE"]:
169
+ evalExpr(conf["RE_PUBLIC_MEMBER_VARIABLE"], exp, mockToken, msgType, errors)
170
+
171
+ # Check Global Variable naming
172
+ if "RE_GLOBAL_VARNAME" in conf and conf["RE_GLOBAL_VARNAME"]:
173
+ for var in cfg.variables:
174
+ if (var.access is None) or var.access != 'Global':
175
+ continue
176
+ mockToken = DataStruct(var.typeStartToken.file, var.typeStartToken.linenr, var.nameToken.str)
177
+ msgType = 'Public member variable'
178
+ for exp in conf["RE_GLOBAL_VARNAME"]:
179
+ evalExpr(conf["RE_GLOBAL_VARNAME"], exp, mockToken, msgType, errors)
180
+
181
+ # Check Functions naming
182
+ if "RE_FUNCTIONNAME" in conf and conf["RE_FUNCTIONNAME"]:
183
+ for token in cfg.tokenlist:
184
+ if token.function:
185
+ if token.function.type in ('Constructor', 'Destructor', 'CopyConstructor', 'MoveConstructor'):
186
+ continue
187
+ retval = token.previous.str
188
+ prev = token.previous
189
+ while "*" in retval and len(retval.replace("*", "")) == 0:
190
+ prev = prev.previous
191
+ retval = prev.str + retval
192
+ if debugprint:
193
+ print("\t:: {} {}".format(retval, token.function.name))
194
+
195
+ if retval and retval in conf["function_prefixes"]:
196
+ if not token.function.name.startswith(conf["function_prefixes"][retval]):
197
+ errors.append(reportError(
198
+ token.file, token.linenr, 'style', 'Function ' + token.function.name + ' violates naming convention'))
199
+ mockToken = DataStruct(token.file, token.linenr, token.function.name)
200
+ msgType = 'Function'
201
+ for exp in conf["RE_FUNCTIONNAME"]:
202
+ evalExpr(conf["RE_FUNCTIONNAME"], exp, mockToken, msgType, errors)
203
+
204
+ # Check Class naming
205
+ if "RE_CLASS_NAME" in conf and conf["RE_CLASS_NAME"]:
206
+ for fnc in cfg.functions:
207
+ # Check if it is Constructor/Destructor
208
+ if fnc.type == 'Constructor' or fnc.type == 'Destructor':
209
+ mockToken = DataStruct(fnc.tokenDef.file, fnc.tokenDef.linenr, fnc.name)
210
+ msgType = 'Class ' + fnc.type
211
+ for exp in conf["RE_CLASS_NAME"]:
212
+ evalExpr(conf["RE_CLASS_NAME"], exp, mockToken, msgType, errors)
213
+ return errors
214
+
215
+
216
+ if __name__ == "__main__":
217
+ parser = argparse.ArgumentParser(description='Naming verification')
218
+ parser.add_argument('dumpfiles', type=str, nargs='+',
219
+ help='A set of dumpfiles to process')
220
+ parser.add_argument("--debugprint", action="store_true", default=False,
221
+ help="Add debug prints")
222
+ parser.add_argument("--configfile", type=str, default="naming.json",
223
+ help="Naming check config file")
224
+ parser.add_argument("--verify", action="store_true", default=False,
225
+ help="verify this script. Must be executed in test folder !")
226
+
227
+ args = parser.parse_args()
228
+ errors = process(args.dumpfiles, args.configfile, args.debugprint)
229
+
230
+ if args.verify:
231
+ print(errors)
232
+ if len(errors) < 6:
233
+ print("Not enough errors found")
234
+ sys.exit(1)
235
+ target = [
236
+ '[namingng_test.c:8] ( style ) naming.py: Variable badui32 violates naming convention\n',
237
+ '[namingng_test.c:11] ( style ) naming.py: Variable a violates naming convention\n',
238
+ '[namingng_test.c:29] ( style ) naming.py: Variable badui32 violates naming convention\n',
239
+ '[namingng_test.c:20] ( style ) naming.py: Function ui16bad_underscore violates naming convention\n',
240
+ '[namingng_test.c:25] ( style ) naming.py: Function u32Bad violates naming convention\n',
241
+ '[namingng_test.c:37] ( style ) naming.py: Function Badui16 violates naming convention\n']
242
+ diff = set(errors) - set(target)
243
+ if len(diff):
244
+ print("Not the right errors found {}".format(str(diff)))
245
+ sys.exit(1)
246
+ print("Verification done\n")
247
+ sys.exit(0)
248
+
249
+ if len(errors):
250
+ print('Found errors: {}'.format(len(errors)))
251
+ sys.exit(1)
252
+
253
+ sys.exit(0)
@@ -0,0 +1,12 @@
1
+ import cppcheckdata, cppcheck, runpy, sys, os
2
+
3
+ if __name__ == '__main__':
4
+ addon = sys.argv[1]
5
+ __addon_name__ = os.path.splitext(os.path.basename(addon))[0]
6
+ sys.argv.pop(0)
7
+
8
+ runpy.run_path(addon, run_name='__main__')
9
+
10
+ # Run registered checkers
11
+ cppcheck.runcheckers()
12
+ sys.exit(cppcheckdata.EXIT_CODE)
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # This script analyses Cppcheck dump files to locate threadsafety issues
4
+ # - warn about static local objects
5
+ #
6
+
7
+ import cppcheckdata
8
+ import sys
9
+
10
+ def reportError(token, severity, msg, id):
11
+ cppcheckdata.reportError(token, severity, msg, 'threadsafety', id)
12
+
13
+
14
+ def checkstatic(data):
15
+ for var in data.variables:
16
+ if var.isStatic and var.isLocal:
17
+ type = None
18
+ if var.isClass:
19
+ type = 'object'
20
+ else:
21
+ type = 'variable'
22
+ if var.isConst:
23
+ if data.standards.cpp == 'c++03':
24
+ reportError(var.typeStartToken, 'warning', 'Local constant static ' + type + ' \'' + var.nameToken.str + '\', dangerous if it is initialized in parallel threads', 'threadsafety-const')
25
+ else:
26
+ reportError(var.typeStartToken, 'warning', 'Local static ' + type + ': ' + var.nameToken.str, 'threadsafety')
27
+
28
+ for arg in sys.argv[1:]:
29
+ if arg.startswith('-'):
30
+ continue
31
+
32
+ print('Checking %s...' % arg)
33
+ data = cppcheckdata.CppcheckData(arg)
34
+
35
+ for cfg in data.iterconfigurations():
36
+ print('Checking %s, config %s...' % (arg, cfg.name))
37
+ checkstatic(cfg)
38
+
39
+ sys.exit(cppcheckdata.EXIT_CODE)
@@ -0,0 +1,252 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ # cppcheck addon for Y2038 safeness detection
4
+ #
5
+ # Detects:
6
+ #
7
+ # 1. _TIME_BITS being defined to something else than 64 bits
8
+ # 2. _USE_TIME_BITS64 being defined when _TIME_BITS is not
9
+ # 3. Any Y2038-unsafe symbol when _USE_TIME_BITS64 is not defined.
10
+ #
11
+ # Example usage:
12
+ # $ cppcheck --dump path-to-src/test.c
13
+ # $ y2038.py path-to-src/test.c.dump
14
+ #
15
+ # y2038.py will walk the source tree for .dump files.
16
+ from __future__ import print_function
17
+
18
+ import cppcheckdata
19
+ import sys
20
+ import os
21
+ import re
22
+
23
+
24
+ # --------------------------------------------
25
+ # #define/#undef detection regular expressions
26
+ # --------------------------------------------
27
+
28
+ # test for '#define _TIME_BITS 64'
29
+ re_define_time_bits_64 = re.compile(r'^\s*#\s*define\s+_TIME_BITS\s+64\s*$')
30
+
31
+ # test for '#define _TIME_BITS ...' (combine w/ above to test for 'not 64')
32
+ re_define_time_bits = re.compile(r'^\s*#\s*define\s+_TIME_BITS\s+.*$')
33
+
34
+ # test for '#undef _TIME_BITS' (if it ever happens)
35
+ re_undef_time_bits = re.compile(r'^\s*#\s*undef\s+_TIME_BITS\s*$')
36
+
37
+ # test for '#define _USE_TIME_BITS64'
38
+ re_define_use_time_bits64 = re.compile(r'^\s*#\s*define\s+_USE_TIME_BITS64\s*$')
39
+
40
+ # test for '#undef _USE_TIME_BITS64' (if it ever happens)
41
+ re_undef_use_time_bits64 = re.compile(r'^\s*#\s*undef\s+_USE_TIME_BITS64\s*$')
42
+
43
+ # --------------------------------
44
+ # List of Y2038-unsafe identifiers
45
+ # --------------------------------
46
+
47
+ # This is WIP. Eventually it should contain all identifiers (types
48
+ # and functions) which would be affected by the Y2038 bug.
49
+
50
+ id_Y2038 = {
51
+ # Y2038-unsafe types by definition
52
+ 'time_t'
53
+ # Types using Y2038-unsafe types
54
+ 'lastlog',
55
+ 'msqid_ds',
56
+ 'semid_ds',
57
+ 'timeb',
58
+ 'timespec',
59
+ 'timeval',
60
+ 'utimbuf',
61
+ 'itimerspec',
62
+ 'stat',
63
+ 'clnt_ops',
64
+ 'elf_prstatus',
65
+ 'itimerval',
66
+ 'ntptimeval',
67
+ 'rusage',
68
+ 'timex',
69
+ 'utmp',
70
+ 'utmpx',
71
+ # APIs using 2038-unsafe types
72
+ 'ctime',
73
+ 'ctime_r',
74
+ 'difftime',
75
+ 'gmtime',
76
+ 'gmtime_r',
77
+ 'localtime',
78
+ 'localtime_r',
79
+ 'mktime',
80
+ 'stime',
81
+ 'timegm',
82
+ 'timelocal',
83
+ 'time',
84
+ 'msgctl',
85
+ 'ftime',
86
+ 'aio_suspend',
87
+ 'clock_getres',
88
+ 'clock_gettime',
89
+ 'clock_nanosleep',
90
+ 'clock_settime',
91
+ 'futimens',
92
+ 'mq_timedreceive',
93
+ 'mq_timedsend',
94
+ 'nanosleep',
95
+ 'pselect',
96
+ 'pthread_cond_timedwait',
97
+ 'pthread_mutex_timedlock',
98
+ 'pthread_rwlock_timedrdlock',
99
+ 'pthread_rwlock_timedwrlock',
100
+ 'sched_rr_get_interval',
101
+ 'sem_timedwait',
102
+ 'sigtimedwait',
103
+ 'timespec_get',
104
+ 'utimensat',
105
+ 'adjtime',
106
+ 'pmap_rmtcall',
107
+ 'clntudp_bufcreate',
108
+ 'clntudp_create',
109
+ 'futimes',
110
+ 'gettimeofday',
111
+ 'lutimes',
112
+ 'select',
113
+ 'settimeofday',
114
+ 'utimes',
115
+ 'utime',
116
+ 'timerfd_gettime',
117
+ 'timerfd_settime',
118
+ 'timer_gettime',
119
+ 'timer_settime',
120
+ 'fstatat',
121
+ 'fstat',
122
+ '__fxstatat',
123
+ '__fxstat',
124
+ 'lstat',
125
+ '__lxstat',
126
+ 'stat',
127
+ '__xstat',
128
+ 'struct itimerval',
129
+ 'setitimer',
130
+ 'getitimer',
131
+ 'ntp_gettime',
132
+ 'getrusage',
133
+ 'wait3',
134
+ 'wait4',
135
+ 'adjtimex',
136
+ 'ntp_adjtime',
137
+ 'getutent_r',
138
+ 'getutent',
139
+ 'getutid_r',
140
+ 'getutid',
141
+ 'getutline_r',
142
+ 'getutline',
143
+ 'login',
144
+ 'pututline',
145
+ 'updwtmp',
146
+ 'getutxent',
147
+ 'getutxid',
148
+ 'getutxline',
149
+ 'pututxline'
150
+ }
151
+
152
+
153
+ def check_y2038_safe(dumpfile, quiet=False):
154
+ # Assume that the code is Y2038 safe until proven otherwise
155
+ y2038safe = True
156
+ # load XML from .dump file
157
+ data = cppcheckdata.CppcheckData(dumpfile)
158
+
159
+ # Convert dump file path to source file in format generated by cppcheck.
160
+ # For example after the following call:
161
+ # cppcheck ./src/my-src.c --dump
162
+ # We got 'src/my-src.c' value for 'file' field in cppcheckdata.
163
+ srcfile = dumpfile.rstrip('.dump')
164
+ srcfile = os.path.expanduser(srcfile)
165
+ srcfile = os.path.normpath(srcfile)
166
+
167
+ # go through each configuration
168
+ for cfg in data.iterconfigurations():
169
+ if not quiet:
170
+ print('Checking %s, config %s...' % (srcfile, cfg.name))
171
+ safe_ranges = []
172
+ safe = -1
173
+ time_bits_defined = False
174
+ srclinenr = '0'
175
+
176
+ for directive in cfg.directives:
177
+ # track source line number
178
+ if directive.file == srcfile:
179
+ srclinenr = directive.linenr
180
+ # check for correct _TIME_BITS if present
181
+ if re_define_time_bits_64.match(directive.str):
182
+ time_bits_defined = True
183
+ elif re_define_time_bits.match(directive.str):
184
+ cppcheckdata.reportError(directive, 'error',
185
+ '_TIME_BITS must be defined equal to 64',
186
+ 'y2038',
187
+ 'type-bits-not-64')
188
+ time_bits_defined = False
189
+ y2038safe = False
190
+ elif re_undef_time_bits.match(directive.str):
191
+ time_bits_defined = False
192
+ # check for _USE_TIME_BITS64 (un)definition
193
+ if re_define_use_time_bits64.match(directive.str):
194
+ safe = int(srclinenr)
195
+ # warn about _TIME_BITS not being defined
196
+ if not time_bits_defined:
197
+ cppcheckdata.reportError(directive, 'warning',
198
+ '_USE_TIME_BITS64 is defined but _TIME_BITS was not',
199
+ 'y2038',
200
+ 'type-bits-undef')
201
+ elif re_undef_use_time_bits64.match(directive.str):
202
+ unsafe = int(srclinenr)
203
+ # do we have a safe..unsafe area?
204
+ if unsafe > safe > 0:
205
+ safe_ranges.append((safe, unsafe))
206
+ safe = -1
207
+
208
+ # check end of source beyond last directive
209
+ if len(cfg.tokenlist) > 0:
210
+ unsafe = int(cfg.tokenlist[-1].linenr)
211
+ if unsafe > safe > 0:
212
+ safe_ranges.append((safe, unsafe))
213
+
214
+ # go through all tokens
215
+ for token in cfg.tokenlist:
216
+ if token.str in id_Y2038:
217
+ if not any(lower <= int(token.linenr) <= upper
218
+ for (lower, upper) in safe_ranges):
219
+ cppcheckdata.reportError(token, 'warning',
220
+ token.str + ' is Y2038-unsafe',
221
+ 'y2038',
222
+ 'unsafe-call')
223
+ y2038safe = False
224
+ token = token.next
225
+
226
+ return y2038safe
227
+
228
+
229
+ def get_args_parser():
230
+ parser = cppcheckdata.ArgumentParser()
231
+ return parser
232
+
233
+
234
+ if __name__ == '__main__':
235
+ parser = get_args_parser()
236
+ args = parser.parse_args()
237
+
238
+ exit_code = 0
239
+ quiet = not any((args.quiet, args.cli))
240
+
241
+ if not args.dumpfile:
242
+ if not args.quiet:
243
+ print("no input files.")
244
+ sys.exit(0)
245
+
246
+ for dumpfile in args.dumpfile:
247
+ if not args.quiet:
248
+ print('Checking ' + dumpfile + '...')
249
+
250
+ check_y2038_safe(dumpfile, quiet)
251
+
252
+ sys.exit(cppcheckdata.EXIT_CODE)