Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.
日本語の概要は準備中です。原文の説明を表示しています。
Use when C code is written or audited and needs a pure-C baseline: standard, undefined behavior, integer and buffer safety, sanitizers, fuzzing, build flags. Not for C++: use modern-cpp-practices.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
This skill is a pure-C policy. It never prescribes a C++ idiom (RAII, destructors, smart pointers, lock guards, containers) as C practice. C++ code goes to modern-cpp-practices.
| Field | Bound contract |
|---|---|
| Trigger | C code is being written, audited, or hardened and the project needs one baseline for the C standard, undefined behavior, integer and buffer safety, the sanitizer and fuzzing matrix, and build and CI hardening flags. |
| Authority | Read-only. Writes nothing. Chat output only. No remote mutation. |
| Side effect | Emits a guidance report to chat. No source or build file is modified. |
| Done | The report names the C standard with the compiler that supports it, the undefined-behavior catalog with the sanitizer that traps each entry, the integer and buffer rules with their checked-arithmetic form, the hardening flag set the identified compiler accepts, the sanitizer and fuzzing jobs for CI, and the findings the audit checklist produced. |
-std= value or the project-agreed standard.CMakeLists.txt, meson.build, Makefile, CI job files.Identify the compiler, its version, and the active C standard from build files (CMakeLists.txt, meson.build, Makefile, compiler command lines) or from the inputs. Record whether the code is C++ anywhere in the tree. When the compiler or standard cannot be determined, report the ambiguity and stop. Done when: compiler, version, and standard are named, or the ambiguity is reported.
Select the C standard. C23 (ISO/IEC 9899:2024) is the current published standard. Pin -std=c23 when the compiler accepts it. GCC 16.2 and Clang 23.1.0 both accept -std=c23. Fall back to -std=c17 on an older toolchain and list which C23 controls the fallback loses (<stdckdint.h>, static_assert as a keyword, nullptr, [[nodiscard]] and the other standard attributes). Use -std=c23 or -std=c17, not the gnu spellings, unless the code needs a GNU extension and a comment names it. Done when: the standard is selected and the compiler's support is recorded.
Catalog undefined behavior. Undefined behavior is not implementation-defined and not "works on my machine": it is permission for the optimizer to assume the program never does the thing. A single instance on a reachable path can delete a bounds check or miscompile a loop, and a clean debug build proves nothing. Scan for the high-frequency classes and report each occurrence with file:line:
INT_MAX + 1 is UB, so the compiler may assume x + 1 > x and remove the overflow check. Unsigned overflow wraps by definition and is not UB, but a wrap that feeds a size is still a bug.memcpy or through a union; char and unsigned char may alias anything.<stdatomic.h> or a mutex.const object, a call through a function pointer of the wrong type, and an infinite loop with no side effects.
Done when: every occurrence of a cataloged class is listed, or the report states that none was found.Apply the integer and buffer rules. Report each violation with file:line:
memcpy length, or a loop bound. Overflow into a small allocation followed by a large copy is the classic remote code execution shape.ckd_add, ckd_sub, and ckd_mul from <stdckdint.h> under C23, or __builtin_add_overflow, __builtin_sub_overflow, and __builtin_mul_overflow on GCC and Clang under C17.size_t for sizes and indexes. Guard the order of an unsigned subtraction: a - b wraps when b > a and the result passes every upper-bound check.-Wconversion -Wsign-conversion and fix narrowing and sign changes at the source.snprintf and explicit length checks over unbounded copies. Never compute ptr + n from an attacker-controlled n before comparing n against the real remaining length.realloc returning NULL must not overwrite the original pointer, or the block leaks. Use a temporary.malloc, calloc, or realloc with exactly one free on every exit path, and every fopen with fclose. Use the goto-cleanup idiom, a single exit label that releases what was acquired, so an early error return cannot skip a release.gets (removed in C11; use fgets), strcpy and strcat (use snprintf or strlcpy where the platform provides it), sprintf and vsprintf (use snprintf and vsnprintf), scanf("%s") without a width (add a width or parse by hand), system and popen with interpolated input (use posix_spawn or execve with an argument vector), strtok (use strtok_r), alloca and a VLA sized from input (use the heap with a checked size), atoi and atol (use strtol with range and errno checks).printf(user) reads and writes memory through %n. Write printf("%s", user) and compile with -Wformat -Wformat=2 -Werror=format-security.rand or random for keys, tokens, IVs, or salts. Use getrandom(2) or arc4random_buf where the platform provides it, or a vetted library.explicit_bzero or memset_s where available). A plain memset before a free can be optimized away.assert is compiled out under -DNDEBUG, which the common release presets set. A bounds or validation check written as assert does not exist in the shipped binary. Write it as an explicit if that returns or aborts, and keep assert for internal invariants.realpath before checking them, prefer openat with O_NOFOLLOW, and operate on file descriptors to avoid check-then-use races.
Done when: every violation is listed with its replacement.Recommend the hardening flag set. Report the flags the identified compiler accepts, split by compiler where support differs. Do not edit build files. Both GCC 16.2 and Clang 23.1.0 accept:
-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wshadow -Wcast-align -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wformat=2 -Wshift-overflow=2 -Wvla -Wbidi-chars=any -Wtrampolines, with -Werror in CI. A clean -Wall -Wextra build is the floor, not the goal.-O2 -D_FORTIFY_SOURCE=3 -fstack-protector-strong -fstack-clash-protection -fstrict-flex-arrays=3 -ftrivial-auto-var-init=zero.-fcf-protection=full.-fPIE -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack, and -Wl,-z,nodlopen for an executable that no one loads with dlopen.-ffile-prefix-map=<src>=. and SOURCE_DATE_EPOCH, so a path or timestamp does not leak into the binary. Keep -g and ship split debug symbols.
GCC only: -fhardened (an umbrella that enables a subset of the above; verify the subset against the GCC version in use) and -fzero-init-padding-bits=all. Clang rejects both. Missing hardening flags on a network-facing or setuid binary is a HIGH finding. Done when: the flag set is listed per compiler with each unsupported flag named.Recommend the sanitizer and fuzzing matrix. Sanitizers ship inside GCC 16.2 and Clang 23.1.0 under -fsanitize=. They are for test and CI builds, never production: production uses the flag set from step 5.
-fsanitize=address,undefined -fno-sanitize-recover=all -fsanitize-address-use-after-scope, then the full test suite. Any abort is a CRITICAL or HIGH finding. Set ASAN_OPTIONS=detect_leaks=1:strict_string_checks=1 and UBSAN_OPTIONS=print_stacktrace=1.-fsanitize=thread. ASan and TSan cannot run in one binary.-fsanitize=integer to catch defined-but-suspicious unsigned wrap. -ftrapv is the blunter GCC and Clang alternative for signed overflow.-fsanitize=fuzzer and receives bug fixes only, so an existing libFuzzer target stays supported but a new one belongs on AFL++. Pair every fuzz build with ASan and UBSan. Keep a seed corpus and a regression corpus in the repository. A new crash is a CRITICAL finding.clang-tidy with bugprone-*, cert-*, clang-analyzer-*, misc-*, performance-*, and portability-*, committed in .clang-tidy, and GCC -fanalyzer in a CI job. Commit a .clang-format and enforce it with clang-format --dry-run --Werror.Run the audit checklist against the tree and report each hit with its severity. Every command below is grep -rnE over *.c and *.h:
\b(gets|strcpy|strcat|sprintf|vsprintf|scanf|system|popen|strtok|atoi|atol)\s*\(.alloca and VLAs sized from input, HIGH: \balloca\s*\(, plus a build with -Wvla to list every VLA, then read each hit for the source of its size.(printf|fprintf|snprintf|syslog|err|warn)\s*\([^"]*\).(malloc|calloc|realloc|alloca)\s*\([^;]*[*+][^;]*\), then check for ckd_ or __builtin_.*_overflow in the same function.\b(access|stat|lstat)\s*\(, then check whether the following open uses the checked name.\b(rand|random|srand)\s*\(.memcmp on a buffer named like a MAC, token, secret, or digest.= (malloc|calloc|realloc)\( hit not followed by a NULL check._FORTIFY_SOURCE, stack-protector, relro, fcf-protection, or PIE in the build files.fsanitize, afl, or fuzzer in the CI configuration.
Done when: every checklist line has run and each hit is in the report with a severity.Verify every recommendation against the compiler and standard named in step 1. Drop a flag the compiler rejects and record the drop. Drop every C++ prescription that a source or a prior draft carries as C policy and list it under dropped prescriptions. Done when: every recommendation is verified and the dropped list is complete.
| Failure class | Behavior |
|---|---|
| Compiler or standard undetermined | Report the ambiguity with the evidence examined. Do not guess. Guidance is blocked until both are named. |
| C23 unsupported | Fall back to -std=c17 and list the C23 controls that are lost, with the C17 replacement for each (__builtin_*_overflow for <stdckdint.h>, _Static_assert for static_assert). |
| Hardening flag rejected | Omit it, name the compiler that rejects it, and recommend the subset that compiles cleanly. |
| Sanitizer unavailable on the platform | Name the missing sanitizer, recommend Valgrind Memcheck as the fallback, and state what it misses. |
| C++ found in the tree | Report the C++ files and route them to modern-cpp-practices. Apply this baseline to the C files only. |
| Prescription found that is a C++ idiom | Drop it from the report and list it under dropped prescriptions. |
No partial result is claimed complete. When a step cannot finish, the report states which steps succeeded and which are blocked.
A guidance report with these sections:
| Section | Content |
|---|---|
| C standard | C23 or C17, with the compiler and version that justify the choice and the controls a C17 fallback loses. |
| Undefined behavior catalog | Each cataloged class found in the code, with file:line and the sanitizer that traps it. |
| Integer and buffer rules | Each violation with its checked-arithmetic, bounded, or ownership replacement. |
| Hardening flags | The flag set per compiler, with every rejected flag named. |
| Sanitizer and fuzzing matrix | The CI jobs, fuzz targets, static analysis configuration, and dependency policy. |
| Audit findings | Each checklist hit with file:line and severity, CRITICAL first. |
| Dropped prescriptions | Every C++ idiom cut from a source or draft because it does not apply to C. |
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.
日本語の概要は準備中です。原文の説明を表示しています。
Use when configuring ADC sampling time, DMA-driven ADC, calibration, or DAC channel setup on bare-metal MCUs. Not for the DMA stream itself: use dma-baremetal.
日本語の概要は準備中です。原文の説明を表示しています。
Use when creating AF_XDP sockets, configuring UMEM and XSK rings, writing an XDP redirect program, or choosing copy versus zero-copy mode. Not for full kernel bypass: use dpdk.
日本語の概要は準備中です。原文の説明を表示しています。
Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.
日本語の概要は準備中です。原文の説明を表示しています。
Use when a redacted, trimmed agent transcript must be appended to a GitHub PR or issue body, with human approval and preview. Not for automated or model-initiated insertion.
日本語の概要は準備中です。原文の説明を表示しています。
Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential, publish, deploy, or irreversible changes.
日本語の概要は準備中です。原文の説明を表示しています。