Skip to content

Commit e84499e

Browse files
committed
y2038: eliminate false positives with automatic build system detection
The Y2038 addon currently generates false positive warnings when scanning codebases that are properly configured for Y2038 safety through build system flags, making it impractical for comprehensive codebase analysis. This prevents teams from running Y2038 checks across entire projects in CI/CD pipelines due to noise from correctly configured code. Add automatic build system detection to discover Y2038-related compiler flags (_TIME_BITS=64, _FILE_OFFSET_BITS=64, _USE_TIME_BITS64) from: - Makefile variants (Makefile, makefile, GNUmakefile, *.mk) - CMake files (CMakeLists.txt, *.cmake) - Meson build files (meson.build) - Autotools scripts (configure, configure.ac, configure.in) - Compiler flags passed via cppcheck -D options When proper Y2038 configuration is detected (both _TIME_BITS=64 AND _FILE_OFFSET_BITS=64), suppress Y2038 warnings and display an informational message indicating the configuration source. Implement hierarchical directory search up to 5 levels from source files to locate relevant build files, with flag precedence: build system > compiler flags > source code #define directives. Add performance optimizations: - Intelligent file caching with TTL-based invalidation - UTF-8 BOM handling for cross-platform compatibility - Robust import fallback system Extend test suite with comprehensive coverage: - Compiler flag parsing edge cases (18 test scenarios) - Build system detection for all supported formats - Caching behavior and performance validation - Cross-platform file encoding handling This enables organizations to run comprehensive Y2038 analysis on entire codebases without false positives from properly configured projects, while maintaining detection of actual Y2038 safety issues.
1 parent 4780cd2 commit e84499e

10 files changed

Lines changed: 1388 additions & 165 deletions

File tree

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ Ludvig Gunne Lindström
238238
Luis Díaz Más
239239
Luís Pereira
240240
Lukas Grützmacher
241+
Lukas Hiesmayr
241242
Lukasz Czajczyk
242243
Łukasz Jankowski
243244
Luxon Jean-Pierre

addons/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Addons are scripts that analyses Cppcheck dump files to check compatibility with
1616
Enforces naming conventions across the code. Enhanced version with support for type prefixes in variable and function names.
1717
+ [findcasts.py](https://github.com/danmar/cppcheck/blob/main/addons/findcasts.py)
1818
Locates casts in the code.
19+
+ [y2038_buildsystem.py](https://github.com/danmar/cppcheck/blob/main/addons/y2038_buildsystem.py)
20+
Detects and parses build system files to extract compiler flags for Y2038 analysis. Supports multiple build systems including Make, CMake, Meson, Autotools, and Bazel.
1921
+ [misc.py](https://github.com/danmar/cppcheck/blob/main/addons/misc.py)
2022
Performs miscellaneous checks.
2123

addons/doc/y2038.md

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
# README of the Y2038 cppcheck addon
2+
3+
## Contents
4+
5+
- [What is Y2038?](#what-is-y2038)
6+
- [What is the Y2038 cppcheck addon?](#what-is-the-y2038-cppcheck-addon)
7+
- [How does the Y2038 cppcheck addon work?](#how-does-the-y2038-cppcheck-addon-work)
8+
- [How to use the Y2038 cppcheck addon](#how-to-use-the-y2038-cppcheck-addon)
9+
10+
---
11+
12+
## What is Y2038?
13+
14+
In a few words:
15+
16+
In Linux, the current date and time is kept as the number of seconds elapsed
17+
since the Unix epoch, that is, since January 1st, 1970 at 00:00:00 GMT.
18+
19+
Most of the time, this representation is stored as a 32-bit signed quantity.
20+
21+
On January 19th, 2038 at 03:14:07 GMT, such 32-bit representations will reach
22+
their maximum positive value.
23+
24+
What happens then is unpredictable: system time might roll back to December
25+
13th, 1901 at 19:55:13, or it might keep running on until February 7th, 2106
26+
at 06:28:15 GMT, or the computer may freeze, or just about anything you can
27+
think of, plus a few ones you can't.
28+
29+
The workaround for this is to switch to a 64-bit signed representation of time
30+
as seconds from the Unix epoch. This representation will work for more than 250
31+
billion years.
32+
33+
Working around Y2038 requires fixing the Linux kernel, the C libraries, and
34+
any user code around which uses 32-bit epoch representations.
35+
36+
There is Y2038-proofing work in progress on the Linux and GNU glibc front.
37+
38+
## What is the Y2038 cppcheck addon?
39+
40+
The Y2038 cppcheck addon is a tool to help detect code which might need fixing
41+
because it is Y2038-unsafe. This may be because it uses types or functions from
42+
GNU libc or from the Linux kernel which are known not to be Y2038-proof.
43+
44+
## How does the Y2038 cppcheck addon work?
45+
46+
The Y2038 cppcheck addon takes XML dumps produced by `cppcheck` from source code
47+
files and looks for the names of types or functions which are known to be Y2038-
48+
unsafe, and emits diagnostics whenever it finds one.
49+
50+
Of course, this is of little use if your code uses a Y2038-proof glibc and
51+
correctly configured Y2038-proof time support.
52+
53+
This is why `y2038.py` takes into account preprocessor directives like
54+
`_TIME_BITS`, `__USE_TIME_BITS64`, and `_FILE_OFFSET_BITS`.
55+
56+
The addon now features comprehensive build system detection and compiler flag
57+
checking that eliminates false positives when projects are properly configured
58+
for Y2038 safety. This enables analysis of entire codebases without being
59+
overwhelmed by warnings from correctly configured code.
60+
61+
### Key improvements in this version:
62+
63+
* **Eliminate false positives**: Automatically suppress Y2038 warnings when proper
64+
configuration is detected (both `_TIME_BITS=64` AND `_FILE_OFFSET_BITS=64`)
65+
66+
* **Comprehensive codebase analysis**: Run Y2038 checks across entire projects
67+
without manual flag specification - the addon discovers build configurations
68+
automatically
69+
70+
* **Multi-build-system support**: Detects Y2038 flags from Makefile, CMake,
71+
Meson, Autotools, and other build systems with hierarchical directory search
72+
73+
* **Smart warning suppression**: When proper Y2038 configuration is found,
74+
displays informational messages instead of false warnings
75+
76+
* **Enterprise-ready**: Suitable for CI/CD pipelines and large-scale code analysis
77+
78+
### Build System Detection:
79+
The addon automatically searches for and parses the following build files:
80+
- Makefiles (`Makefile`, `makefile`, `GNUmakefile`, `*.mk`)
81+
- CMake files (`CMakeLists.txt`, `*.cmake`)
82+
- Configure scripts (`configure`, `configure.ac`, `configure.in`)
83+
- Meson build files (`meson.build`)
84+
- Other build systems (`BUILD`, `BUILD.bazel`, etc.)
85+
86+
The addon searches up to 5 directory levels from the source file location to
87+
find relevant build files and extracts Y2038-related compiler definitions.
88+
89+
### Warning Suppression:
90+
When proper Y2038 configuration is detected (both `_TIME_BITS=64` AND
91+
`_FILE_OFFSET_BITS=64` defined), Y2038 warnings are automatically suppressed
92+
with an informational message indicating the source of the configuration.
93+
94+
### Priority order for Y2038 flag detection (highest to lowest):
95+
1. Build system files (`Makefile`, `CMakeLists.txt`, etc.)
96+
2. Compiler flags (`-D` options passed to `cppcheck`)
97+
3. Source code `#define` directives
98+
99+
`_TIME_BITS` is defined equal to 64 by user code when it wants 64-bit time
100+
support from the GNU glibc. Code which does not define `_TIME_BITS` equal to 64
101+
(or defines it to something else than 64) runs a risk of not being Y2038-proof.
102+
103+
`__USE_TIME_BITS64` is defined by the GNU glibc when it actually provides 64-bit
104+
time support. When this is defined, then all glibc symbols, barring bugs, are
105+
Y2038-proof (but your code might have its own Y2038 bugs, if it handles signed
106+
32-bit Unix epoch values).
107+
108+
The Y2038 cppcheck performs the following checks:
109+
110+
1. Upon meeting a definition for `_TIME_BITS`, if that definition does not
111+
set it equal to 64, this error diagnostic is emitted:
112+
113+
```
114+
Error: _TIME_BITS must be defined equal to 64
115+
```
116+
117+
This case is very unlikely but might result from a typo, so pointing
118+
it out is quite useful. Note that definitions of `_TIME_BITS` as an
119+
expression evaluating to 64 will be flagged too.
120+
121+
2. Upon meeting a definition for `_USE_TIME_BITS64`, if `_TIME_BITS` is not
122+
defined equal to 64, this information diagnostic is emitted:
123+
124+
```
125+
Warning: _USE_TIME_BITS64 is defined but _TIME_BITS was not
126+
```
127+
128+
This reflects the fact that even though the glibc checked default to
129+
64-bit time support, this was not requested by the user code, and
130+
therefore the user code might fail Y2038 if built against a glibc
131+
which defaults to 32-bit time support.
132+
133+
3. Upon meeting a symbol (type or function) which is known to be Y2038-
134+
unsafe, if proper Y2038 configuration is not detected, this warning
135+
diagnostic is emitted:
136+
137+
```
138+
Warning: <symbol> is Y2038-unsafe
139+
```
140+
141+
This reflects the fact that the user code is referring to a symbol
142+
which, when glibc defaults to 32-bit time support, might fail Y2038.
143+
144+
However, if proper Y2038 configuration is detected (both `_TIME_BITS=64`
145+
AND `_FILE_OFFSET_BITS=64`), these warnings are suppressed and an
146+
informational message is displayed instead.
147+
148+
General note: `y2038.py` will handle multiple configurations, and will
149+
emit diagnostics for each configuration in turn.
150+
151+
## How to use the Y2038 cppcheck addon
152+
153+
### **Comprehensive Codebase Analysis**
154+
155+
The enhanced Y2038 addon is designed for analyzing entire codebases efficiently:
156+
157+
```sh
158+
# Analyze all C files in a project - addon will detect build system configs automatically
159+
cppcheck --addon=y2038 .
160+
161+
# For projects with proper Y2038 configuration, you'll see suppression messages instead of false warnings:
162+
# Y2038 warnings suppressed: Found proper Y2038 configuration in build system (_TIME_BITS=64 and _FILE_OFFSET_BITS=64)
163+
```
164+
165+
### **CI/CD Integration**
166+
167+
This addon is now suitable for continuous integration workflows:
168+
169+
```sh
170+
# Example CI script
171+
#!/bin/bash
172+
find . -name "*.c" -exec cppcheck --dump {} \;
173+
python3 addons/y2038.py $(find . -name "*.dump")
174+
175+
# Returns non-zero exit code only for actual Y2038 issues,
176+
# not for properly configured projects
177+
```
178+
179+
### **Basic Usage**
180+
181+
The Y2038 cppcheck addon is used like any other cppcheck addon:
182+
183+
```sh
184+
cppcheck --dump file1.c [ file2.c [...]]
185+
y2038.py file1.c.dump [ file2.c.dump [...]]
186+
```
187+
188+
To use compiler flags for Y2038 checking:
189+
190+
```sh
191+
cppcheck --dump -D_TIME_BITS=64 -D_USE_TIME_BITS64 file1.c
192+
y2038.py file1.c.dump
193+
```
194+
195+
For automatic build system detection (recommended):
196+
197+
```sh
198+
cppcheck --dump file1.c # No flags needed - addon detects from build files
199+
y2038.py file1.c.dump
200+
```
201+
202+
The addon will automatically:
203+
1. Search for build system files (`Makefile`, `CMakeLists.txt`, etc.)
204+
2. Extract Y2038-related compiler definitions
205+
3. Validate `_TIME_BITS` and `_USE_TIME_BITS64` configurations
206+
4. Report any Y2038-unsafe configurations found in build files
207+
208+
Example build system configurations that will be detected:
209+
210+
Makefile:
211+
```makefile
212+
CPPFLAGS = -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64
213+
```
214+
215+
CMakeLists.txt:
216+
```cmake
217+
add_definitions(-D_TIME_BITS=64)
218+
add_definitions(-D_FILE_OFFSET_BITS=64)
219+
```
220+
221+
meson.build:
222+
```meson
223+
add_global_arguments('-D_TIME_BITS=64', language : 'c')
224+
add_project_arguments('-D_FILE_OFFSET_BITS=64', language : 'c')
225+
```
226+
227+
When both `_TIME_BITS=64` and `_FILE_OFFSET_BITS=64` are found, Y2038 warnings
228+
will be suppressed with a message like:
229+
```
230+
Y2038 warnings suppressed: Found proper Y2038 configuration in build system (_TIME_BITS=64 and _FILE_OFFSET_BITS=64)
231+
Suppressed X Y2038-unsafe function warning(s)
232+
```
233+
234+
Sample test C files are provided:
235+
236+
- `test/y2038-test-1-bad-time-bits.c` # Source code with wrong `_TIME_BITS`
237+
- `test/y2038-test-2-no-time-bits.c` # Source code missing `_TIME_BITS`
238+
- `test/y2038-test-3-no-use-time-bits.c` # Missing `_USE_TIME_BITS64`
239+
- `test/y2038-test-4-good.c` # Proper Y2038 setup in source
240+
- `test/y2038-test-5-good-no-time-used.c` # No time functions used
241+
- `test/y2038-test-compiler-flags.c` # Shared test file for compiler flag scenarios:
242+
# - Proper Y2038 config (`-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 -D_USE_TIME_BITS64`)
243+
# - Wrong `_TIME_BITS` value (`-D_TIME_BITS=32`)
244+
# - Incomplete config (`-D_USE_TIME_BITS64` only)
245+
246+
These cover the cases described above. You can run them through cppcheck
247+
and y2038.py to see for yourself how the addon diagnostics look like. If
248+
this README is not outdated (and if it is, feel free to submit a patch),
249+
you can run `cppcheck` on these files as on any others:
250+
251+
```sh
252+
cppcheck --dump addons/test/y2038/y2038-*.c
253+
python3 addons/y2038.py addons/test/y2038/y2038-*.dump
254+
```
255+
256+
For testing compiler flag functionality (using the shared test file):
257+
258+
```sh
259+
# Test proper Y2038 configuration
260+
cppcheck --dump -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 -D_USE_TIME_BITS64 addons/test/y2038/y2038-test-compiler-flags.c
261+
python3 addons/y2038.py addons/test/y2038/y2038-test-compiler-flags.c.dump
262+
263+
# Test wrong _TIME_BITS value
264+
cppcheck --dump -D_TIME_BITS=32 addons/test/y2038/y2038-test-compiler-flags.c
265+
python3 addons/y2038.py addons/test/y2038/y2038-test-compiler-flags.c.dump
266+
267+
# Test incomplete configuration (should produce warnings)
268+
cppcheck --dump -D_USE_TIME_BITS64 addons/test/y2038/y2038-test-compiler-flags.c
269+
python3 addons/y2038.py addons/test/y2038/y2038-test-compiler-flags.c.dump
270+
```
271+
272+
If you have not installed cppcheck yet, you will have to run these
273+
commands from the root of the cppcheck repository:
274+
275+
```sh
276+
make
277+
sudo make install
278+
./cppcheck --dump addons/test/y2038/y2038-*.c
279+
PYTHONPATH=addons python3 addons/y2038.py addons/test/y2038/y2038-*.c.dump
280+
```
281+
282+
In both cases, `y2038.py` execution should result in the following:
283+
284+
```
285+
Checking addons/y2038/test/y2038-test-1-bad-time-bits.c.dump...
286+
Checking addons/y2038/test/y2038-test-1-bad-time-bits.c.dump, config ""...
287+
Checking addons/y2038/test/y2038-test-2-no-time-bits.c.dump...
288+
Checking addons/y2038/test/y2038-test-2-no-time-bits.c.dump, config ""...
289+
Checking addons/y2038/test/y2038-test-3-no-use-time-bits.c.dump...
290+
Checking addons/y2038/test/y2038-test-3-no-use-time-bits.c.dump, config ""...
291+
Checking addons/y2038/test/y2038-test-4-good.c.dump...
292+
Checking addons/y2038/test/y2038-test-4-good.c.dump, config ""...
293+
# Configuration "":
294+
# Configuration "":
295+
[addons/y2038/test/y2038-test-1-bad-time-bits.c:8]: (error) _TIME_BITS must be defined equal to 64
296+
[addons/y2038/test/y2038-inc.h:9]: (warning) _USE_TIME_BITS64 is defined but _TIME_BITS was not
297+
[addons/y2038/test/y2038-test-1-bad-time-bits.c:10]: (information) addons/y2038/test/y2038-inc.h was included from here
298+
[addons/y2038/test/y2038-inc.h:9]: (warning) _USE_TIME_BITS64 is defined but _TIME_BITS was not
299+
[addons/y2038/test/y2038-test-2-no-time-bits.c:8]: (information) addons/y2038/test/y2038-inc.h was included from here
300+
[addons/y2038/test/y2038-test-3-no-use-time-bits.c:13]: (warning) timespec is Y2038-unsafe
301+
[addons/y2038/test/y2038-test-3-no-use-time-bits.c:15]: (warning) clock_gettime is Y2038-unsafe
302+
```
303+
304+
Note: `y2038.py` recognizes option `--template` as `cppcheck` does, including
305+
pre-defined templates 'gcc', 'vs' and 'edit'. The short form `-t` is also
306+
recognized.

0 commit comments

Comments
 (0)