Commit Graph

15 Commits

Author SHA1 Message Date
f1283e21a3 Enforce status-code ownership and harden the name registry
Reservations were advisory bookkeeping: any component could name any status,
so the registry only detected declared-range overlap between components that
both opted in. Naming a status now requires a reservation.
akerr_register_status_name() checks that the range belongs to the caller, and
the legacy two-argument akerr_name_for_status() set path, which cannot
identify its caller, requires that some reservation covers the status. Every
refusal is logged and names the real owner, because a name that fails to
register degrades that code to "Unknown Error" in every later stack trace.

Fix a reservation made before the first PREPARE_ERROR being silently
discarded. akerr_init() clears the tables, so whichever component first
triggered it wiped an earlier reservation and the next component to claim the
same range was told it was free, producing exactly the undetected aliasing
the registry exists to prevent. Every registry entry point now calls
akerr_init(), which sets its guard before doing any work so those calls do
not recurse.

Replace the linear-scan name array with an open-addressed hash table, taking
lookup from O(n) to O(1) and raising usable capacity from 512 entries (366
free to consumers after errno registration) to 3072 (~2900 free). Both table
sizes are build-time overridable and applied PRIVATE: they live entirely in
src/error.c, so raising them cannot desynchronize a library from its
consumers the way AKERR_MAX_ERR_VALUE could. Exhausting either table is now
logged and returned to the caller rather than silently dropping the entry.
No dynamic allocation is introduced; both tables remain file-scope arrays,
and the library's undefined-symbol set gains only strcmp and strlen.

Register names for AKERR_EOF, AKERR_ITERATOR_BREAK and AKERR_NOT_IMPLEMENTED,
which had none and rendered as "Unknown Error" in every stack trace carrying
them. err_error_names.c now sweeps the whole AKERR_* offset span so a code
added without a name fails there instead of in production traces.

Add static assertions that the slot count is a power of two and that
AKERR_BADEXC stays inside the library's own 0-255 band, the latter guarding
against a host errno space large enough to push library codes into the range
consumers are told to allocate from.

Set a project version and soname (1.0.0 / libakerror.so.1) so a stale
installed library can no longer be silently paired with newer headers, and so
akerror.pc ships a real Version field instead of an empty one.

Mutation testing surfaced an out-of-bounds probe in the new table that the
suite did not catch: masking with SLOTS rather than SLOTS-1 indexes past the
array, and err_maxval.c asserted only that some names registered before the
table filled, which a collapsed probe sequence still satisfies. It now
requires a substantial entry count and reads every entry back by its own
distinct name.

Tests: 28/28 pass. Coverage 99.4% line / 86.8% branch. Mutation score for
src/error.c 74% -> 77.3%.

Compatibility: source and ABI break. AKERR_MAX_ERR_VALUE and the
__AKERR_ERROR_NAMES data symbol are gone, custom codes must move out of
0-255, and names must be registered against a reserved range. README.md
carries the migration steps.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 18:19:25 -04:00
11d21068df Add collision-safe status code registry
Replace the consumer-sized status-name array with private sparse storage and accept arbitrary integer status values. Add explicit range reservations with overlap diagnostics, reserve the library's 0-255 compatibility band, and harden pointer and string boundary handling.

Update regression coverage and document the required migration for custom status-code consumers.
2026-07-30 13:53:52 -04:00
4212ff0b28 Fix format-string use of __FILE__/__func__ and name_for_status lower bound
All checks were successful
libakerror CI Build / cmake_build (push) Successful in 2m48s
libakerror CI Build / mutation_test (push) Successful in 7m40s
Two hardening fixes flagged by the earlier review:

1. FAIL passed __FILE__ and __func__ directly as the snprintf format string.
   __FILE__ expands to a string literal that could contain a '%' (a build path
   under a directory with a percent sign), and __func__ is not a literal at all;
   either way snprintf would read nonexistent varargs. Pass them as "%s"
   arguments instead.

2. akerr_name_for_status guarded the upper bound but not the lower one, so a
   negative status indexed __AKERR_ERROR_NAMES[negative] -- an out-of-bounds
   read, or an out-of-bounds write when a name was supplied. Reject status < 0.

Regression tests err_format_string (uses #line to put a conversion specifier in
__FILE__) and err_name_bounds fail against the old code (verified) and pass now.
Full suite: 23/23, no warnings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-28 10:52:29 -04:00
675c60b5e0 Removed AKERR_HEAP, AKERR_REGISTRY, AKERR_BEHAVIOR, they belong to libakgl. Replaced AKERR_BEHAVIOR which was ambiguous with AKERR_BADEXC which is raised when a function falls to call SUCCEED_RETURN(). 2026-06-22 08:15:07 -04:00
93f5e93480 Add an error type for circular references 2026-06-02 17:12:14 -04:00
235033d633 VALID() wasn't properly handling NULL returns, leading to false positives 2026-05-24 19:14:35 -04:00
166a478e6a Add AKERR_EOF, properly call akerr_init_errno 2026-05-12 16:42:33 -04:00
0c29f5d69f Fix handling of CATCH() or FAIL() macros around functions that should return an (akerr_ErrorContext *) but return an invalid pointer (to something not in our exception array) 2026-05-06 12:36:56 -04:00
c526bb1ba3 Cleanup the code and unified everything (except the macros) under the akerr_ namespace 2026-01-10 10:20:35 -05:00
6821752ec7 Change naming convention for the error context array to avoid confusion about whether it is dynamic or static 2026-01-10 09:50:17 -05:00
cf0f2bbeac Make stdlib optional. Remove dependency on SDL3. Update README. 2026-01-05 21:18:44 -05:00
428b59c83f Fix some minor issues on the __ERROR_NAMES 2025-08-02 23:03:51 -04:00
0521ebaf7d Better support for user-defined error codes and messages 2025-08-02 15:07:08 -04:00
826676dca2 Move from Makefile to CMake 2025-07-20 22:02:21 -04:00
052f7a078a Add library 2025-07-20 21:40:14 -04:00