Improve C++ Builder 5 Code Quality with These Source Code Scanners

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

  1. 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.
  2. Normalize headers: create stubs or wrappers for platform-specific headers that modern tools cannot parse; optionally point tools at a cleaned copy.
  3. Convert or document nonstandard extensions: list Borland-specific attributes, pragmas, and calling conventions so you can suppress or map them for analysers.
  4. 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

  1. Prioritize findings: high-severity security issues, definite memory-safety bugs, and crashes first.
  2. Suppress false positives via tool-specific suppression lists or inline annotations.
  3. Create custom rules for recurring patterns unique to your codebase.
  4. 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)

  1. Prepare code with include paths and stubs.
  2. Run Cppcheck + Flawfinder + semgrep.
  3. Triage and fix high-severity items.
  4. Re-run and reduce noise via suppressions.
  5. 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

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *