Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Core/Source/SolidSyslogCrc16.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ enum
{
CRC16_CCITT_INIT = 0xFFFFU,
CRC16_CCITT_POLY = 0x1021U,
BITS_PER_BYTE = 8U,
MSB_MASK = 0x8000U
};

Expand All @@ -24,9 +23,9 @@ uint16_t SolidSyslogCrc16_Compute(const uint8_t* data, uint16_t length)
{
crc ^= (uint16_t) ((uint16_t) data[i] << 8U);

for (int bit = 0; bit < BITS_PER_BYTE; bit++)
for (uint_fast8_t bit = 0; bit < 8U; bit++)
{
if ((crc & MSB_MASK) != 0)
if ((crc & MSB_MASK) != 0U)
{
crc = (uint16_t) ((crc << 1) ^ CRC16_CCITT_POLY);
}
Expand Down
11 changes: 5 additions & 6 deletions Core/Source/SolidSyslogCrc16Policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ enum
static void Crc16Policy_Crc16ComputeIntegrity(const uint8_t* data, uint16_t length, uint8_t* integrityOut);
static bool Crc16Policy_Crc16VerifyIntegrity(const uint8_t* data, uint16_t length, const uint8_t* integrityIn);

static struct SolidSyslogSecurityPolicy instance = {
CRC16_SIZE,
Crc16Policy_Crc16ComputeIntegrity,
Crc16Policy_Crc16VerifyIntegrity,
};

struct SolidSyslogSecurityPolicy* SolidSyslogCrc16Policy_Create(void)
{
static struct SolidSyslogSecurityPolicy instance = {
CRC16_SIZE,
Crc16Policy_Crc16ComputeIntegrity,
Crc16Policy_Crc16VerifyIntegrity,
};
return &instance;
}

Expand Down
12 changes: 6 additions & 6 deletions Core/Source/SolidSyslogNullMutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
static void NullMutex_Lock(struct SolidSyslogMutex* base);
static void NullMutex_Unlock(struct SolidSyslogMutex* base);

static struct SolidSyslogMutex instance;
static struct SolidSyslogMutex NullMutex_Instance;

struct SolidSyslogMutex* SolidSyslogNullMutex_Create(void)
{
instance.Lock = NullMutex_Lock;
instance.Unlock = NullMutex_Unlock;
return &instance;
NullMutex_Instance.Lock = NullMutex_Lock;
NullMutex_Instance.Unlock = NullMutex_Unlock;
return &NullMutex_Instance;
}

void SolidSyslogNullMutex_Destroy(void)
{
instance.Lock = NULL;
instance.Unlock = NULL;
NullMutex_Instance.Lock = NULL;
NullMutex_Instance.Unlock = NULL;
}

static void NullMutex_Lock(struct SolidSyslogMutex* base)
Expand Down
11 changes: 5 additions & 6 deletions Core/Source/SolidSyslogNullSecurityPolicy.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,13 @@ static bool NullSecurityPolicy_NullVerifyIntegrity(const uint8_t* data, uint16_t
return true;
}

static struct SolidSyslogSecurityPolicy instance = {
0,
NullSecurityPolicy_NullComputeIntegrity,
NullSecurityPolicy_NullVerifyIntegrity,
};

struct SolidSyslogSecurityPolicy* SolidSyslogNullSecurityPolicy_Create(void)
{
static struct SolidSyslogSecurityPolicy instance = {
0,
NullSecurityPolicy_NullComputeIntegrity,
NullSecurityPolicy_NullVerifyIntegrity,
};
return &instance;
}

Expand Down
108 changes: 108 additions & 0 deletions DEVLOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,113 @@
# Dev Log

## 2026-05-17 — S10.13 Security policies + CRC + Sync primitives conformance (#383)

Second per-group conformance story in E10, applying the S10.12 pilot
recipe to the Security policies + CRC + Sync primitives group. Cleared
all warning-mode findings raised by `analyze-tidy` and
`analyze-cppcheck` (with the cppcheck-misra addon) against
`SolidSyslogCrc16.{c,h}`, `SolidSyslogCrc16Policy.{c,h}`,
`SolidSyslogNullSecurityPolicy.{c,h}`, `SolidSyslogSecurityPolicyDefinition.h`,
`SolidSyslogMutex.{c,h}`, `SolidSyslogMutexDefinition.h`,
`SolidSyslogNullMutex.{c,h}` and the three Platform mutex impls
(`SolidSyslogPosixMutex.{c,h}`, `SolidSyslogWindowsMutex.{c,h}`,
`SolidSyslogFreeRtosMutex.{c,h}`).

### MISRA fixes — three new findings, each reviewed per-site

- 1× rule 5.9 in `SolidSyslogNullMutex.c` — bare `instance` collided
with the same name in `SolidSyslogNullSecurityPolicy.c` and
`SolidSyslogCrc16Policy.c`. Renamed to `NullMutex_Instance` per the
S10.08 / S10.12 `<Class>_Instance` convention. Couldn't move into
`_Create` because `_Destroy` also touches it.
- 2× rule 8.9 (advisory) in `SolidSyslogNullSecurityPolicy.c` and
`SolidSyslogCrc16Policy.c` — file-scope `static instance` only read
in `_Create`. Moved into `_Create` as block-scope statics, matching
the S10.12 `QUEUE_NAME_PREFIX` recipe.

No new deviations. No new `cppcheck-suppress` comments. No count bumps
to existing deviations (D.002 / D.003 / D.010) — no new sites accrued
to those.

### CRC-16 inner-loop review

`SolidSyslogCrc16.c` had zero warning-mode findings, so this was a
deliberate "walk the loop and decide whether to tighten anything
anyway" pass. Three small changes landed:

- `int bit` → `uint_fast8_t bit` — match the comparand's unsigned
essential type. cppcheck-misra's chosen 10.4 subset doesn't flag
the signed/unsigned mix in `for`-loop bounds, but it's still the
right type.
- `!= 0` → `!= 0U` — match the U-suffixed literal style used
elsewhere in the file (S10.10 sweep convention).
- Dropped the `BITS_PER_BYTE = 8U` enum constant; inlined `8U`.

### Decisions

- **Drop `BITS_PER_BYTE`, inline the literal.** Switching the loop
variable to `uint_fast8_t` unmasked clang-tidy's
`bugprone-too-small-loop-variable`, because anonymous-enum constants
in C have essential type `int` regardless of the `U` suffix on
their literal. clang-tidy compared the 8-bit `uint_fast8_t`
variable against the 32-bit `int` bound and flagged it. Three fixes
Comment on lines +52 to +53

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In C99/C11/C17, is uint_fast8_t guaranteed to be exactly 8 bits, or only at least 8 bits?

💡 Result:

In C99, C11, and C17, the type uint_fast8_t is guaranteed to be an unsigned integer type with a width of at least 8 bits [1][2][3]. It is not guaranteed to be exactly 8 bits [4][5]. The C standard defines uint_fastN_t as the fastest unsigned integer type available on the implementation that has a width of at least N bits [1][3]. Because the implementation may choose a larger type (such as 16, 32, or 64 bits) if it is more efficient for the target architecture's word size or alignment requirements, uint_fast8_t can be wider than 8 bits [4][5]. In contrast, the type uint8_t is defined as an unsigned integer type with a width of exactly 8 bits, but it is an optional type and is not guaranteed to be provided by all implementations [2][6]. If an implementation does not support an 8-bit type, uint8_t will not be defined, whereas uint_fast8_t and uint_least8_t are required to be provided [1][4][3].

Citations:


🏁 Script executed:

head -60 DEVLOG.md | tail -20

Repository: DavidCozens/solid-syslog

Length of output: 1010


Correct uint_fast8_t description from "8-bit" to at least 8 bits.

At lines 52–53, the note describes uint_fast8_t as "8-bit". In C, uint_fast8_t is guaranteed to be at least 8 bits and may be wider (16, 32, or 64 bits) on many targets. The phrasing is misleading in technical documentation.

Consider clarifying:

Proposed revision
-  their literal. clang-tidy compared the 8-bit `uint_fast8_t`
-  variable against the 32-bit `int` bound and flagged it. Three fixes
+  their literal. clang-tidy compared the `uint_fast8_t` variable
+  (which may be wider than 8 bits depending on the target) against
+  the `int`-typed bound and flagged it. Three fixes
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
their literal. clang-tidy compared the 8-bit `uint_fast8_t`
variable against the 32-bit `int` bound and flagged it. Three fixes
their literal. clang-tidy compared the `uint_fast8_t` variable
(which may be wider than 8 bits depending on the target) against
the `int`-typed bound and flagged it. Three fixes
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DEVLOG.md` around lines 52 - 53, Update the DEVLOG note that currently calls
uint_fast8_t "8-bit" to state it is "at least 8 bits" (or similar wording) so it
reflects the C guarantee that uint_fast8_t may be wider on many targets; locate
the sentence mentioning uint_fast8_t in the paragraph around the existing text
and replace "8-bit `uint_fast8_t`" with "at least 8-bit `uint_fast8_t`" or
"minimum 8-bit `uint_fast8_t`" to clarify the guarantee.

considered:
- (A) inline the literal `8U` (clang-tidy's `MagnitudeBitsUpperLimit`
default 16 skips small-literal warnings — 8's magnitude is 3 bits,
well below the threshold);
- (B) promote `BITS_PER_BYTE` out of the enum to
`static const uint8_t` (type-honest but diverges from the
tree-wide enum convention for one constant);
- (C) widen the loop variable to `unsigned` (keeps the enum form
but loses the "explicitly small unsigned" semantic).
Went with (A) — `BITS_PER_BYTE` was a one-use named constant whose
meaning ("there are 8 bits in a byte") is self-evident from the
surrounding CRC code. The other CRC enum constants
(`CRC16_CCITT_INIT`, `CRC16_CCITT_POLY`, `MSB_MASK`) carry
non-obvious values and retain their names.

- **Anonymous-enum constants in C are `int`, not the literal's type.**
Surfaced explicitly during the CRC review: even when the literal is
`0x1021U` (essentially unsigned), the enum constant the literal
initialises is typed `int` per C99 §6.7.2.2. This is a quirk of
the form, not a bug — within cast-wrapped bitwise ops (as in
`(uint16_t) ((crc << 1) ^ CRC16_CCITT_POLY)`) the boundary cast
normalises the essential type. But it does mean enum constants
can't always stand in for typed integer constants without surprise
— e.g. as the upper bound of a narrow-typed loop. Worth knowing
for future per-group stories.

### Scope rule observation

The scoped cppcheck-misra re-runs we used during fix-verification
flagged additional 2.4 findings on `Crc16.c` / `Crc16Policy.c` that
didn't appear in the full-tree run. Re-confirmed the S10.12 scope
rule: trust the **full-tree** invocation as the source of truth.
Scoped runs are useful for fast iteration but can produce different
output because cppcheck-misra's rule subset behaves differently when
fewer translation units are visible.

### Gates

- `cmake --preset tidy && cmake --build --preset tidy` — clean
(0 findings).
- `cmake --preset debug && cmake --build --preset debug --target junit`
— 1122 tests, 0 failures.
- `cmake --preset clang-debug && cmake --build --preset clang-debug --target junit`
— 1122 tests, 0 failures.
- `cmake --preset sanitize && cmake --build --preset sanitize --target junit`
— 1122 tests, 0 failures.
- `cmake --preset coverage && cmake --build --preset coverage --target coverage`
— 100% line coverage on every Linux-buildable file in scope. (Tree
overall: 99.6% lines / 99.0% functions, well above the 90% gate.)
- Standalone non-MISRA `cppcheck Core/Source/` — clean (0 findings).
- Standalone `cppcheck --addon=misra` full tree — zero findings on
S10.13 scope files.
- `clang-format --dry-run --Werror` on edited files — clean.

Windows / BDD / OpenSSL integration are CI's responsibility per the
CLAUDE.md workflow note.

## 2026-05-16 — S10.12 Pilot — Buffer group conformance + anonymous-enum policy (#381)

First per-group conformance story in E10. Cleared all warning-mode
Expand Down
Loading