Rainer Gerhards ec82ed7c00
docs: formalize defensive coding and assertion patterns
Standardizing how we handle "impossible" states to help automated
tools detect bugs while keeping production code simple and stable.
This modernization step aids maintainability and AI-assisted reviews.

BEFORE: No formalized guidance for "impossible" path handling.
AFTER: Mandatory assertions with optional defensive fallbacks.

Introduced a formalized hybrid pattern for defensive programming.
The new guidance mandates the use of assert() for all invariants
to allow Static Analyzers and AI agents to reason about code state
correctly. It also recommends an optional defensive if fallback
to prevent production crashes, except where recovery logic would be
excessively complex. Updated the top-level AGENTS.md with a brief
instruction and added a detailed practice document to the
coding_practices catalog. Prohibited use of __builtin_unreachable()
to prevent undefined behavior in release builds.

AI-Agent: Antigravity
2025-12-21 17:44:54 +01:00

35 lines
1.3 KiB
ReStructuredText

.. _defensive-coding-and-assertions:
Defensive Coding and Assertions
===============================
**Classification**: Pattern
**Context**: Handling "impossible" states or logic paths that should theoretically never be reached.
**Why it matters**:
Rsyslog prioritizes production stability. We use Static Analysis (SA) and CI to detect bugs. ``assert()`` tells analyzers/AI that a state is invalid. Defensive checks protect production from crashes if the "impossible" happens.
**Steps**:
1. **Mandatory Assertion**: Always use ``assert()`` to define the invariant. This informs SA tools and AI assistants that this state is invalid.
2. **Optional Defensive Fallback**: Follow the assert with an ``if`` check to handle the failure gracefully. This is recommended but optional if the fallback handler would be excessively complex or introduce more risk than it solves.
3. **No UB**: Never use ``__builtin_unreachable()``.
4. **Order**: Place the ``assert()`` before the defensive check.
**Example**:
.. code-block:: c
/* 1. Inform SA/AI */
assert(pPtr != NULL);
/* 2. Defensive check (optional if complex) */
if (pPtr == NULL) {
LogMsg(0, NO_ERRCODE, LOG_ERR, "logic error: pPtr is NULL");
return;
}
/* 3. Logic */
do_something(pPtr);