How to Scan C++ Builder 5 Code: Recommended Tools and Workflow
C++ Builder 5 is an older IDE and toolchain (circa early 2000s). Scanning its source effectively requires tools that can handle legacy C++ dialects, preprocessor-heavy code, and possibly platform-specific extensions. Below is a practical, actionable workflow and recommended tools for static analysis, security scanning, and build-integrated checks.
1) Goals and scope
- Primary goals: find bugs (memory, logic), detect security vulnerabilities (buffer overflows, format-string, unsafe APIs), enforce style/consistency, and locate dead/unused code.
- Scope: scan pure C/C++ sources (.cpp, .c, .h), resource files, and build scripts. If code relies on Borland/Embarcadero-specific headers or RTL/VCL, expect false positives and adjust rules.
2) Recommended tools (legacy-friendly and general)
- Flawfinder — lightweight C/C++ security scanner; good for quick scans and spotting risky API usage.
- RATS (Rough Auditing Tool for Security) — another simple security scanner for C/C++ that flags risky functions.
- Cppcheck — actively maintained static analyzer for C/C++; flexible and configurable; can run on legacy code with tuned suppressions.
- Clang-tidy (where usable) — powerful checks but may struggle with very old compiler extensions; consider running on code after making it parseable with modern Clang (see notes).
- Sparse — primarily for Linux kernel style checks but can catch certain issues in C; limited for C++.
- Commercial/advanced tools (if available): PVS-Studio, Coverity, Klocwork — these have broader rule sets and better handling of complex C++ but require licensing and may need project adjustments to parse legacy constructs.
- Grep/sed/semgrep — use semgrep for pattern-based rules and custom checks; grep/sed for quick ad-hoc searches.
3) Prepare the codebase
- Create a reproducible build environment: isolate the code, gather include paths and macros from C++ Builder 5 project files (.bpr/.dpr/.dproj), and export a compile command database where possible.
- Normalize headers: create stubs or wrappers for platform-specific headers that modern tools cannot parse; optionally point tools at a cleaned copy.
- Convert or document nonstandard extensions: list Borland-specific attributes, pragmas, and calling conventions so you can suppress or map them for analysers.
- Exclude generated code and third-party libraries to reduce noise.
4) Configure tools and run baseline scans
- Run Cppcheck with project include paths, set language to C++98/C++03 if supported, and enable relevant checks: cppcheck –enable=all –std=c++03 –suppressions-list=…
- Run Flawfinder and RATS for quick security issues: flawfinderrats -w
- Try semgrep with custom patterns for unsafe functions (strcpy, sprintf, gets): semgrep –config path/to/custom-rules/
- If using commercial tools, run their project importers and tune analysis settings to match C++ Builder dialect.
5) Triage and tune
- Prioritize findings: high-severity security issues, definite memory-safety bugs, and crashes first.
- Suppress false positives via tool-specific suppression lists or inline annotations.
- Create custom rules for recurring patterns unique to your codebase.
- Iterate — re-run scans after suppressions and fixes to reduce noise.
6) Integrate into workflow
- Add static scans to CI where feasible. If CI builds use modern toolchains, run scans on a sanitized copy or within a VM/container that reproduces the legacy build environment.
- Use pre-commit or nightly jobs to catch regressions.
- Include security scanners (Flawfinder/semgrep) as separate jobs for faster results.
7) Fixing and verifying issues
- Tackle high-impact fixes first (buffer overflows, unchecked format strings, pointer misuse).
- Write tests around changed modules; where unit tests aren’t available, write small harnesses to exercise risky code paths.
- Re-scan after fixes and run runtime sanitizers when possible (AddressSanitizer, Valgrind) — note: ASan requires modern toolchain; Valgrind can run binaries if built for supported platforms.
8) Practical tips for C++ Builder 5 specifics
- Expect many false positives from modern analyzers due to Borland extensions; maintain a mapping file of those extensions.
- If maintaining the legacy toolchain is essential, consider creating a VM image with C++ Builder 5; some commercial analyzers can be pointed at such builds for more accurate parsing.
- When adopting modern tools (clang/clang-tidy), consider a phased modernisation: first make code parseable (guard extensions), then progressively enable stricter checks.
9) Minimal recommended pipeline (practical)
- Prepare code with include paths and stubs.
- Run Cppcheck + Flawfinder + semgrep.
- Triage and fix high-severity items.
- Re-run and reduce noise via suppressions.
- Integrate scans into nightly CI or pre-commit hooks.
10) Example command set (replace paths/options as needed)
- cppcheck: cppcheck –enable=all –std=c++03 –inconclusive –suppress=missingIncludeSystem –project=compile_commands.json
- flawfinder: flawfinder –minlevel=1 src/
- semgrep: semgrep –config ./rules/ c_src/
If you want, I can: produce a ready-to-run Cppcheck/semgrep config tuned for C++ Builder 5
Leave a Reply