code-review-cpp
Security review of C / C++ code — memory-safety and the classic unsafe-API sinks. Load when reviewing C/C++ source/PR, on .c/.cc/.cpp/.h in scope, or "review this C code". Signals: Makefile/CMakeLists
SKILL.mdskills/code-review/code-review-cpp/SKILL.md
GitHubC / C++ source review
When it applies
Reviewing native C/C++ (a service, a parser, a library). The bugs are overwhelmingly memory safety — the highest-impact, most exploitable class — plus the handful of unsafe APIs that cause them.
Why it works
C/C++ has no bounds checking: a length mistake, a lifetime mistake, or attacker-controlled format string becomes a memory-corruption primitive. Most of these trace to a small, greppable set of APIs and patterns, and sanitizers/fuzzing confirm the ones static reading only suspects.
Sinks & patterns (grep, then reason about lengths and lifetimes)
- Buffer overflow:
strcpy,strcat,sprintf,gets,scanf("%s"),memcpy/memmovewith an unchecked or attacker-influenced length; fixed stack buffers filled from input. - Format string:
printf(user),fprintf(f, user),syslog(user)— user data as the format arg. - Integer issues: size/length arithmetic that can overflow or go negative and then feeds an
allocation or copy (
malloc(n*size),len-1); signed/unsigned confusion in bounds checks. - Use-after-free / double-free:
freethen use; ownership unclear across functions; dangling pointers after realloc; C++ iterator invalidation, dangling references,std::movemisuse. - Off-by-one / OOB:
<=in loop bounds, missing NUL terminator,strncpynot null-terminating. - Command/path:
system/popen/exec*with concatenated input; unchecked../in path handling. - C++ specifics: unchecked
.at()vs[], unsafereinterpret_cast, deserialization of untrusted data into objects,std::string↔C-string length mistakes.
Method
- Run
clang --analyze/cppcheckandsemgrep; treat as leads. rg 'strcpy|strcat|sprintf|gets|memcpy|system\(|printf\s*\([^"]'and, for each, trace the size and the source of the data.- For every allocation/copy, check the length's origin and arithmetic for overflow.
- Where reachable with input, confirm with a fuzzer + ASan (
libFuzzer/AFL++) — a crash under ASan is proof; escalate toexploit-memory-corruptionfor exploitability.
Gotchas
- A crash isn't automatically exploitable, but under ASan it's a real memory-safety bug worth reporting.
- Modern C++ (
std::span,std::string_view, smart pointers) reduces but doesn't remove these — raw buffers and FFI boundaries are where they persist. strncpy/snprintfare safer but have their own truncation/termination traps — read the lengths.
References
CERT C/C++ Coding Standard; OWASP C-Based Toolchain hardening; ASan/libFuzzer docs.