From a7e53d974ebc78ad1bc32b325f65b86de87d8344 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Fri, 15 May 2026 18:12:11 +0100 Subject: [PATCH 01/12] refactor: S10.10 fix MISRA 5.6 in SOLIDSYSLOG_STATIC_ASSERT polyfill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Append __LINE__ via two-step concat so each typedef expansion produces a unique name within a translation unit, satisfying MISRA C:2012 Rule 5.6 (typedef name shall be a unique identifier). cppcheck-misra: rule 5.6 findings 5 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Source/SolidSyslogMacros.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Core/Source/SolidSyslogMacros.h b/Core/Source/SolidSyslogMacros.h index d195d72a..32013c9b 100644 --- a/Core/Source/SolidSyslogMacros.h +++ b/Core/Source/SolidSyslogMacros.h @@ -2,8 +2,15 @@ #define SOLIDSYSLOGMACROS_H /* Portable compile-time assertion. Uses the negative-array-size trick - which works from C89 through C23 and all C++ versions — no C11 required. */ -/* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) */ -#define SOLIDSYSLOG_STATIC_ASSERT(cond, msg) typedef char solidsyslog_static_assert_[(cond) ? 1 : -1] + which works from C89 through C23 and all C++ versions — no C11 required. + The two-step concat with __LINE__ makes each typedef name unique within a + translation unit, satisfying MISRA C:2012 Rule 5.6 (typedef name shall be + a unique identifier). */ +/* NOLINTBEGIN(cppcoreguidelines-macro-usage) */ +#define SOLIDSYSLOG_STATIC_ASSERT_CONCAT_INNER(a, b) a##b +#define SOLIDSYSLOG_STATIC_ASSERT_CONCAT(a, b) SOLIDSYSLOG_STATIC_ASSERT_CONCAT_INNER(a, b) +#define SOLIDSYSLOG_STATIC_ASSERT(cond, msg) \ + typedef char SOLIDSYSLOG_STATIC_ASSERT_CONCAT(solidsyslog_static_assert_, __LINE__)[(cond) ? 1 : -1] +/* NOLINTEND(cppcoreguidelines-macro-usage) */ #endif /* SOLIDSYSLOGMACROS_H */ From 7291de51bf0c4a13f0ad54172e6de891d5f522e5 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 07:02:08 +0100 Subject: [PATCH 02/12] refactor: S10.10 fix MISRA 10.4 essential-type mismatches tree-wide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add U suffix to integer literals (and a handful of anonymous-enum initializers and named tunable constants) so each operator's operands share the same MISRA essential-type category. Two byte-comparison sites in SolidSyslog.c (BOM strip) and SolidSyslogFormatter.c (UTF-8 lead range) refactored to use `unsigned char` comparisons with hex literals where the (char) cast did not satisfy cppcheck-misra's essential-type tracking. SOLIDSYSLOG_FORMATTER_STORAGE_SIZE picks up U on the literal inside the macro so every expansion is uniform. cppcheck-misra: rule 10.4 findings 92 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Interface/SolidSyslogBlockStore.h | 4 +-- Core/Interface/SolidSyslogFileBlockDevice.h | 4 +-- Core/Interface/SolidSyslogFormatter.h | 6 ++-- .../SolidSyslogSecurityPolicyDefinition.h | 2 +- Core/Interface/SolidSyslogStreamSender.h | 4 +-- Core/Interface/SolidSyslogTunablesDefaults.h | 2 +- Core/Source/BlockSequence.c | 14 ++++----- Core/Source/RecordStore.h | 2 +- Core/Source/SolidSyslog.c | 9 +++--- Core/Source/SolidSyslogFileBlockDevice.c | 12 +++---- Core/Source/SolidSyslogFormatter.c | 31 ++++++++++--------- Core/Source/SolidSyslogMetaSd.c | 8 ++--- Core/Source/SolidSyslogOriginSd.c | 10 +++--- Core/Source/SolidSyslogTimeQualitySd.c | 8 ++--- Core/Source/SolidSyslogUdpPayload.c | 24 +++++++------- Core/Source/SolidSyslogUdpSender.c | 2 +- .../FatFs/Interface/SolidSyslogFatFsFile.h | 4 +-- .../Interface/SolidSyslogFreeRtosDatagram.h | 4 +-- .../Interface/SolidSyslogFreeRtosMutex.h | 4 +-- .../SolidSyslogFreeRtosStaticResolver.h | 4 +-- .../Interface/SolidSyslogFreeRtosTcpStream.h | 4 +-- .../OpenSsl/Interface/SolidSyslogTlsStream.h | 4 +-- .../Posix/Interface/SolidSyslogPosixFile.h | 4 +-- .../Posix/Interface/SolidSyslogPosixMutex.h | 4 +-- .../Interface/SolidSyslogPosixTcpStream.h | 4 +-- Platform/Posix/Source/SolidSyslogPosixFile.c | 2 +- .../Posix/Source/SolidSyslogPosixHostname.c | 4 +-- .../SolidSyslogPosixMessageQueueBuffer.c | 4 +-- .../Interface/SolidSyslogWindowsFile.h | 4 +-- .../Interface/SolidSyslogWindowsMutex.h | 4 +-- .../Interface/SolidSyslogWinsockTcpStream.h | 4 +-- .../Windows/Source/SolidSyslogWindowsFile.c | 2 +- .../Source/SolidSyslogWindowsHostname.c | 4 +-- 33 files changed, 104 insertions(+), 102 deletions(-) diff --git a/Core/Interface/SolidSyslogBlockStore.h b/Core/Interface/SolidSyslogBlockStore.h index dae67f17..dfc46736 100644 --- a/Core/Interface/SolidSyslogBlockStore.h +++ b/Core/Interface/SolidSyslogBlockStore.h @@ -51,12 +51,12 @@ EXTERN_C_BEGIN enum { SOLIDSYSLOG_BLOCKSTORE_STORAGE_SIZE = - (sizeof(intptr_t) * 32) + SOLIDSYSLOG_MAX_MESSAGE_SIZE + SOLIDSYSLOG_MAX_INTEGRITY_SIZE + 16 + (sizeof(intptr_t) * 32U) + SOLIDSYSLOG_MAX_MESSAGE_SIZE + SOLIDSYSLOG_MAX_INTEGRITY_SIZE + 16U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_BLOCKSTORE_STORAGE_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_BLOCKSTORE_STORAGE_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogBlockStoreStorage; struct SolidSyslogStore* SolidSyslogBlockStore_Create( diff --git a/Core/Interface/SolidSyslogFileBlockDevice.h b/Core/Interface/SolidSyslogFileBlockDevice.h index 7339730d..406aedc8 100644 --- a/Core/Interface/SolidSyslogFileBlockDevice.h +++ b/Core/Interface/SolidSyslogFileBlockDevice.h @@ -12,12 +12,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_FILEBLOCKDEVICE_STORAGE_SIZE = sizeof(intptr_t) * 16 + SOLIDSYSLOG_FILEBLOCKDEVICE_STORAGE_SIZE = sizeof(intptr_t) * 16U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_FILEBLOCKDEVICE_STORAGE_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_FILEBLOCKDEVICE_STORAGE_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogFileBlockDeviceStorage; /* The driver caches at most one open SolidSyslogFile handle, re-pointed only when the diff --git a/Core/Interface/SolidSyslogFormatter.h b/Core/Interface/SolidSyslogFormatter.h index 742fce0c..43abc0ea 100644 --- a/Core/Interface/SolidSyslogFormatter.h +++ b/Core/Interface/SolidSyslogFormatter.h @@ -12,16 +12,16 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_FORMATTER_OVERHEAD = 2 + SOLIDSYSLOG_FORMATTER_OVERHEAD = 2U }; /* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- cannot compute array size as a constexpr in C */ #define SOLIDSYSLOG_FORMATTER_STORAGE_SIZE(bufferSize) \ (SOLIDSYSLOG_FORMATTER_OVERHEAD + \ - (((bufferSize) + sizeof(SolidSyslogFormatterStorage) - 1) / sizeof(SolidSyslogFormatterStorage))) + (((bufferSize) + sizeof(SolidSyslogFormatterStorage) - 1U) / sizeof(SolidSyslogFormatterStorage))) /* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- compile-time worst-case size for EscapedString output */ -#define SOLIDSYSLOG_ESCAPED_MAX_SIZE(maxDecodedLength) (2 * (maxDecodedLength)) +#define SOLIDSYSLOG_ESCAPED_MAX_SIZE(maxDecodedLength) (2U * (maxDecodedLength)) struct SolidSyslogFormatter; diff --git a/Core/Interface/SolidSyslogSecurityPolicyDefinition.h b/Core/Interface/SolidSyslogSecurityPolicyDefinition.h index 1884ebfd..0e47467c 100644 --- a/Core/Interface/SolidSyslogSecurityPolicyDefinition.h +++ b/Core/Interface/SolidSyslogSecurityPolicyDefinition.h @@ -11,7 +11,7 @@ EXTERN_C_BEGIN /* large enough for HMAC-SHA256 (32 bytes); CRC-16 uses 2 */ enum { - SOLIDSYSLOG_MAX_INTEGRITY_SIZE = 32 + SOLIDSYSLOG_MAX_INTEGRITY_SIZE = 32U }; struct SolidSyslogSecurityPolicy diff --git a/Core/Interface/SolidSyslogStreamSender.h b/Core/Interface/SolidSyslogStreamSender.h index 0b61c4ee..047f7f26 100644 --- a/Core/Interface/SolidSyslogStreamSender.h +++ b/Core/Interface/SolidSyslogStreamSender.h @@ -20,12 +20,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_STREAM_SENDER_SIZE = (sizeof(intptr_t) * 7) + sizeof(uint32_t) + SOLIDSYSLOG_STREAM_SENDER_SIZE = (sizeof(intptr_t) * 7U) + sizeof(uint32_t) }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_STREAM_SENDER_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_STREAM_SENDER_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogStreamSenderStorage; struct SolidSyslogSender* SolidSyslogStreamSender_Create( diff --git a/Core/Interface/SolidSyslogTunablesDefaults.h b/Core/Interface/SolidSyslogTunablesDefaults.h index 9ff6b848..dad2c709 100644 --- a/Core/Interface/SolidSyslogTunablesDefaults.h +++ b/Core/Interface/SolidSyslogTunablesDefaults.h @@ -21,7 +21,7 @@ */ #ifndef SOLIDSYSLOG_MAX_MESSAGE_SIZE /* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- macro form required for preprocessor visibility (floor #if) and C array-size const-expr. */ -#define SOLIDSYSLOG_MAX_MESSAGE_SIZE 2048 /* RFC 5424 section 6.1 SHOULD value */ +#define SOLIDSYSLOG_MAX_MESSAGE_SIZE 2048U /* RFC 5424 section 6.1 SHOULD value */ #endif #if SOLIDSYSLOG_MAX_MESSAGE_SIZE < 64 diff --git a/Core/Source/BlockSequence.c b/Core/Source/BlockSequence.c index 34ff3633..dd051506 100644 --- a/Core/Source/BlockSequence.c +++ b/Core/Source/BlockSequence.c @@ -4,21 +4,21 @@ enum { - MIN_MAX_BLOCKS = 2, - MAX_MAX_BLOCKS = 99, - SEQUENCE_MODULUS = 100 + MIN_MAX_BLOCKS = 2U, + MAX_MAX_BLOCKS = 99U, + SEQUENCE_MODULUS = 100U }; static inline uint8_t BlockSequence_NextSequence(uint8_t current) { - return (uint8_t) ((current + 1) % SEQUENCE_MODULUS); + return (uint8_t) ((current + 1U) % SEQUENCE_MODULUS); } static inline size_t BlockSequence_BlockCount(const struct BlockSequence* blockSequence) { return (size_t) ((blockSequence->WriteSequence - blockSequence->OldestSequence + SEQUENCE_MODULUS) % SEQUENCE_MODULUS) + - 1; + 1U; } // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) -- value, min, max have distinct semantics @@ -379,7 +379,7 @@ static inline bool BlockSequence_ThresholdEnabled(const struct BlockSequence* bl static inline bool BlockSequence_IsAboveThreshold(const struct BlockSequence* blockSequence, size_t threshold) { - return (threshold != 0) && (BlockSequence_UsedBytes(blockSequence) >= threshold); + return (threshold != 0U) && (BlockSequence_UsedBytes(blockSequence) >= threshold); } void BlockSequence_MarkWriteBlockCorrupt(struct BlockSequence* blockSequence) @@ -482,7 +482,7 @@ size_t BlockSequence_UsedBytes(const struct BlockSequence* blockSequence) } else { - size_t closedBlocks = BlockSequence_BlockCount(blockSequence) - 1; + size_t closedBlocks = BlockSequence_BlockCount(blockSequence) - 1U; used = (closedBlocks * blockSequence->MaxBlockSize) + blockSequence->WritePosition; } diff --git a/Core/Source/RecordStore.h b/Core/Source/RecordStore.h index accd13f2..34daff2d 100644 --- a/Core/Source/RecordStore.h +++ b/Core/Source/RecordStore.h @@ -12,7 +12,7 @@ struct SolidSyslogBlockDevice; enum { - RECORD_BUFFER_SIZE = 2 + 2 + SOLIDSYSLOG_MAX_MESSAGE_SIZE + SOLIDSYSLOG_MAX_INTEGRITY_SIZE + 1 + RECORD_BUFFER_SIZE = 2U + 2U + SOLIDSYSLOG_MAX_MESSAGE_SIZE + SOLIDSYSLOG_MAX_INTEGRITY_SIZE + 1U }; struct RecordStore diff --git a/Core/Source/SolidSyslog.c b/Core/Source/SolidSyslog.c index 6a70174a..36a72e8c 100644 --- a/Core/Source/SolidSyslog.c +++ b/Core/Source/SolidSyslog.c @@ -369,12 +369,12 @@ static inline bool SolidSyslog_PrivalComponentsAreValid(uint8_t facility, uint8_ static inline bool SolidSyslog_FacilityIsValid(uint8_t facility) { - return facility <= SolidSyslogFacility_Local7; + return facility <= (uint8_t) SolidSyslogFacility_Local7; } static inline bool SolidSyslog_SeverityIsValid(uint8_t severity) { - return severity <= SolidSyslogSeverity_Debug; + return severity <= (uint8_t) SolidSyslogSeverity_Debug; } static inline void SolidSyslog_FormatTimestamp(struct SolidSyslogFormatter* f, SolidSyslogClockFunction clock) @@ -480,7 +480,7 @@ static inline void SolidSyslog_FormatStringField( size_t fieldLength = SolidSyslogFormatter_Length(field); - if (fieldLength > 0) + if (fieldLength > 0U) { SolidSyslogFormatter_PrintUsAsciiString(f, SolidSyslogFormatter_AsFormattedBuffer(field), fieldLength); } @@ -544,7 +544,8 @@ static inline void SolidSyslog_FormatMsg(struct SolidSyslogFormatter* f, const c * so the wire frame contains exactly one. */ static inline const char* SolidSyslog_SkipLeadingBom(const char* msg) { - if ((msg[0] == '\xEF') && (msg[1] == '\xBB') && (msg[2] == '\xBF')) + const unsigned char* bytes = (const unsigned char*) msg; + if ((bytes[0] == 0xEFU) && (bytes[1] == 0xBBU) && (bytes[2] == 0xBFU)) { return msg + 3; } diff --git a/Core/Source/SolidSyslogFileBlockDevice.c b/Core/Source/SolidSyslogFileBlockDevice.c index e858759b..66a7d676 100644 --- a/Core/Source/SolidSyslogFileBlockDevice.c +++ b/Core/Source/SolidSyslogFileBlockDevice.c @@ -12,20 +12,20 @@ struct SolidSyslogFile; enum { - MAX_PATH_SIZE = 128 + MAX_PATH_SIZE = 128U }; static const char FILE_EXTENSION[] = ".log"; enum { - SEQUENCE_DIGITS = 2, - FILENAME_SUFFIX = SEQUENCE_DIGITS + sizeof(FILE_EXTENSION) - 1, - MAX_PREFIX_LENGTH = MAX_PATH_SIZE - FILENAME_SUFFIX - 1, + SEQUENCE_DIGITS = 2U, + FILENAME_SUFFIX = SEQUENCE_DIGITS + sizeof(FILE_EXTENSION) - 1U, + MAX_PREFIX_LENGTH = (size_t) MAX_PATH_SIZE - (size_t) FILENAME_SUFFIX - 1U, /* Two-digit on-disk sequence — indices > 99 cannot be represented * uniquely. Without this guard, a wide blockIndex would be narrowed * to uint8_t and alias an existing block (256 -> 00). */ - MAX_BLOCK_INDEX = 99 + MAX_BLOCK_INDEX = 99U }; static inline bool FileBlockDevice_IsValidBlockIndex(size_t blockIndex) @@ -247,7 +247,7 @@ static inline const char* FileBlockDevice_FormatBlockFilename( SolidSyslogFormatter_BoundedString(formatter, device->PathPrefix, MAX_PREFIX_LENGTH); SolidSyslogFormatter_TwoDigit(formatter, (uint8_t) blockIndex); - SolidSyslogFormatter_BoundedString(formatter, FILE_EXTENSION, sizeof(FILE_EXTENSION) - 1); + SolidSyslogFormatter_BoundedString(formatter, FILE_EXTENSION, sizeof(FILE_EXTENSION) - 1U); return SolidSyslogFormatter_AsFormattedBuffer(formatter); } diff --git a/Core/Source/SolidSyslogFormatter.c b/Core/Source/SolidSyslogFormatter.c index 293f04d7..d8bf9ef2 100644 --- a/Core/Source/SolidSyslogFormatter.c +++ b/Core/Source/SolidSyslogFormatter.c @@ -99,7 +99,7 @@ struct SolidSyslogFormatter* SolidSyslogFormatter_Create(SolidSyslogFormatterSto static inline void Formatter_NullTerminate(struct SolidSyslogFormatter* formatter) { - if (formatter->Size > 0) + if (formatter->Size > 0U) { formatter->Buffer[formatter->Position] = '\0'; } @@ -137,7 +137,7 @@ static inline void Formatter_WriteChar(struct SolidSyslogFormatter* formatter, c static inline bool Formatter_HasCapacity(const struct SolidSyslogFormatter* formatter) { - return (formatter->Size > 0) && (formatter->Position < formatter->Size - 1); + return (formatter->Size > 0U) && (formatter->Position < formatter->Size - 1U); } /* @@ -174,7 +174,7 @@ void SolidSyslogFormatter_BoundedString(struct SolidSyslogFormatter* formatter, else { Formatter_WriteBytes(formatter, REPLACEMENT_CHARACTER, sizeof(REPLACEMENT_CHARACTER)); - len += 1; + len += 1U; } } Formatter_NullTerminate(formatter); @@ -182,7 +182,7 @@ void SolidSyslogFormatter_BoundedString(struct SolidSyslogFormatter* formatter, static inline bool Formatter_CodepointFits(size_t codepointLength, size_t remainingDecodedLength) { - return (codepointLength > 0) && (codepointLength <= remainingDecodedLength); + return (codepointLength > 0U) && (codepointLength <= remainingDecodedLength); } static inline size_t Formatter_Utf8CodepointLength(const char* source) @@ -256,7 +256,8 @@ static inline bool Formatter_IsOverlongFourByteEncoding(char lead, char continua static inline bool Formatter_IsAboveUnicodeMaxEncoding(char lead, char continuation1) { bool f4WithCont1Above8F = (lead == '\xF4') && ((continuation1 & 0xF0) != 0x80); - bool f5OrHigherLead = (lead == '\xF5') || (lead == '\xF6') || (lead == '\xF7'); + unsigned char uLead = (unsigned char) lead; + bool f5OrHigherLead = (uLead >= 0xF5U) && (uLead <= 0xF7U); return f4WithCont1Above8F || f5OrHigherLead; } @@ -304,7 +305,7 @@ static inline bool Formatter_NeedsEscape(char value) static inline bool Formatter_IsExhausted(const struct EscapedContext* context) { - return context->Exhausted || (context->Source[context->SourcePos] == '\0'); + return context->Exhausted || (context->Source[context->SourcePos] == (char) '\0'); } static inline void Formatter_WriteEscaped(struct EscapedContext* context) @@ -320,7 +321,7 @@ static inline void Formatter_WriteEscaped(struct EscapedContext* context) static inline bool Formatter_Fits(const struct EscapedContext* context, size_t decodedAdvance) { - return (decodedAdvance > 0) && (decodedAdvance <= context->MaxDecodedLength - context->DecodedLength); + return (decodedAdvance > 0U) && (decodedAdvance <= context->MaxDecodedLength - context->DecodedLength); } /* NOLINTBEGIN(bugprone-easily-swappable-parameters) -- see forward declaration */ @@ -490,19 +491,19 @@ static inline void Formatter_TrimTruncatedMultiByteTail(struct SolidSyslogFormat size_t p = formatter->Position; size_t trimFrom = p; - if ((p >= 1) && (SolidSyslogUtf8_IsTwoByteLead(buffer[p - 1]) || SolidSyslogUtf8_IsThreeByteLead(buffer[p - 1]) || - SolidSyslogUtf8_IsFourByteLead(buffer[p - 1]))) + if ((p >= 1U) && (SolidSyslogUtf8_IsTwoByteLead(buffer[p - 1U]) || SolidSyslogUtf8_IsThreeByteLead(buffer[p - 1U]) || + SolidSyslogUtf8_IsFourByteLead(buffer[p - 1U]))) { - trimFrom = p - 1; + trimFrom = p - 1U; } - else if ((p >= 2) && - (SolidSyslogUtf8_IsThreeByteLead(buffer[p - 2]) || SolidSyslogUtf8_IsFourByteLead(buffer[p - 2]))) + else if ((p >= 2U) && + (SolidSyslogUtf8_IsThreeByteLead(buffer[p - 2U]) || SolidSyslogUtf8_IsFourByteLead(buffer[p - 2U]))) { - trimFrom = p - 2; + trimFrom = p - 2U; } - else if ((p >= 3) && SolidSyslogUtf8_IsFourByteLead(buffer[p - 3])) + else if ((p >= 3U) && SolidSyslogUtf8_IsFourByteLead(buffer[p - 3U])) { - trimFrom = p - 3; + trimFrom = p - 3U; } for (size_t i = trimFrom; i < p; i++) { diff --git a/Core/Source/SolidSyslogMetaSd.c b/Core/Source/SolidSyslogMetaSd.c index 09200030..6df5c5b8 100644 --- a/Core/Source/SolidSyslogMetaSd.c +++ b/Core/Source/SolidSyslogMetaSd.c @@ -73,7 +73,7 @@ static void MetaSd_Format(struct SolidSyslogStructuredData* self, struct SolidSy { struct SolidSyslogMetaSd* meta = (struct SolidSyslogMetaSd*) self; - SolidSyslogFormatter_BoundedString(formatter, SD_PREFIX, sizeof(SD_PREFIX) - 1); + SolidSyslogFormatter_BoundedString(formatter, SD_PREFIX, sizeof(SD_PREFIX) - 1U); MetaSd_EmitSequenceId(meta, formatter); MetaSd_EmitSysUpTime(meta, formatter); MetaSd_EmitLanguage(meta, formatter); @@ -82,7 +82,7 @@ static void MetaSd_Format(struct SolidSyslogStructuredData* self, struct SolidSy static inline void MetaSd_EmitSequenceId(struct SolidSyslogMetaSd* meta, struct SolidSyslogFormatter* formatter) { - SolidSyslogFormatter_BoundedString(formatter, SEQUENCE_ID_SD, sizeof(SEQUENCE_ID_SD) - 1); + SolidSyslogFormatter_BoundedString(formatter, SEQUENCE_ID_SD, sizeof(SEQUENCE_ID_SD) - 1U); SolidSyslogFormatter_Uint32(formatter, SolidSyslogAtomicCounter_Increment(meta->Counter)); SolidSyslogFormatter_AsciiCharacter(formatter, '"'); } @@ -91,7 +91,7 @@ static inline void MetaSd_EmitSysUpTime(struct SolidSyslogMetaSd* meta, struct S { if (meta->GetSysUpTime != NULL) { - SolidSyslogFormatter_BoundedString(formatter, SYS_UP_TIME_SD, sizeof(SYS_UP_TIME_SD) - 1); + SolidSyslogFormatter_BoundedString(formatter, SYS_UP_TIME_SD, sizeof(SYS_UP_TIME_SD) - 1U); SolidSyslogFormatter_Uint32(formatter, meta->GetSysUpTime()); SolidSyslogFormatter_AsciiCharacter(formatter, '"'); } @@ -101,7 +101,7 @@ static inline void MetaSd_EmitLanguage(struct SolidSyslogMetaSd* meta, struct So { if (meta->GetLanguage != NULL) { - SolidSyslogFormatter_BoundedString(formatter, LANGUAGE_SD, sizeof(LANGUAGE_SD) - 1); + SolidSyslogFormatter_BoundedString(formatter, LANGUAGE_SD, sizeof(LANGUAGE_SD) - 1U); meta->GetLanguage(formatter); SolidSyslogFormatter_AsciiCharacter(formatter, '"'); } diff --git a/Core/Source/SolidSyslogOriginSd.c b/Core/Source/SolidSyslogOriginSd.c index 80b82920..d56e423c 100644 --- a/Core/Source/SolidSyslogOriginSd.c +++ b/Core/Source/SolidSyslogOriginSd.c @@ -87,7 +87,7 @@ static inline void OriginSd_PreFormatStaticPrefix(const struct SolidSyslogOrigin { struct SolidSyslogFormatter* f = SolidSyslogFormatter_Create(instance.FormattedStorage, ORIGIN_FORMATTED_MAX); - SolidSyslogFormatter_BoundedString(f, SD_PREFIX, sizeof(SD_PREFIX) - 1); + SolidSyslogFormatter_BoundedString(f, SD_PREFIX, sizeof(SD_PREFIX) - 1U); OriginSd_EmitSoftware(f, config); OriginSd_EmitSwVersion(f, config); OriginSd_EmitEnterpriseId(f, config); @@ -98,7 +98,7 @@ static inline void OriginSd_EmitSoftware(struct SolidSyslogFormatter* f, const s { if (config->Software != NULL) { - SolidSyslogFormatter_BoundedString(f, SD_SOFTWARE_SD, sizeof(SD_SOFTWARE_SD) - 1); + SolidSyslogFormatter_BoundedString(f, SD_SOFTWARE_SD, sizeof(SD_SOFTWARE_SD) - 1U); SolidSyslogFormatter_EscapedString(f, config->Software, ORIGIN_SOFTWARE_MAX); SolidSyslogFormatter_AsciiCharacter(f, '"'); } @@ -111,7 +111,7 @@ static inline void OriginSd_EmitSwVersion( { if (config->SwVersion != NULL) { - SolidSyslogFormatter_BoundedString(f, SD_VERSION_SD, sizeof(SD_VERSION_SD) - 1); + SolidSyslogFormatter_BoundedString(f, SD_VERSION_SD, sizeof(SD_VERSION_SD) - 1U); SolidSyslogFormatter_EscapedString(f, config->SwVersion, ORIGIN_SWVERSION_MAX); SolidSyslogFormatter_AsciiCharacter(f, '"'); } @@ -124,7 +124,7 @@ static inline void OriginSd_EmitEnterpriseId( { if (config->EnterpriseId != NULL) { - SolidSyslogFormatter_BoundedString(f, SD_ENTERPRISE_ID_SD, sizeof(SD_ENTERPRISE_ID_SD) - 1); + SolidSyslogFormatter_BoundedString(f, SD_ENTERPRISE_ID_SD, sizeof(SD_ENTERPRISE_ID_SD) - 1U); SolidSyslogFormatter_EscapedString(f, config->EnterpriseId, ORIGIN_ENTERPRISE_ID_MAX); SolidSyslogFormatter_AsciiCharacter(f, '"'); } @@ -148,7 +148,7 @@ static inline void OriginSd_EmitIp( size_t index ) { - SolidSyslogFormatter_BoundedString(formatter, SD_IP_SD, sizeof(SD_IP_SD) - 1); + SolidSyslogFormatter_BoundedString(formatter, SD_IP_SD, sizeof(SD_IP_SD) - 1U); origin->GetIpAt(formatter, index); SolidSyslogFormatter_AsciiCharacter(formatter, '"'); } diff --git a/Core/Source/SolidSyslogTimeQualitySd.c b/Core/Source/SolidSyslogTimeQualitySd.c index 234b74f6..7e7f558f 100644 --- a/Core/Source/SolidSyslogTimeQualitySd.c +++ b/Core/Source/SolidSyslogTimeQualitySd.c @@ -51,9 +51,9 @@ static void TimeQualitySd_Format(struct SolidSyslogStructuredData* self, struct tq->GetTimeQuality(&q); - SolidSyslogFormatter_BoundedString(formatter, SD_PREFIX, sizeof(SD_PREFIX) - 1); - TimeQualitySd_FormatBoolParam(formatter, PARAM_TZ_KNOWN, sizeof(PARAM_TZ_KNOWN) - 1, q.TzKnown); - TimeQualitySd_FormatBoolParam(formatter, PARAM_IS_SYNCED, sizeof(PARAM_IS_SYNCED) - 1, q.IsSynced); + SolidSyslogFormatter_BoundedString(formatter, SD_PREFIX, sizeof(SD_PREFIX) - 1U); + TimeQualitySd_FormatBoolParam(formatter, PARAM_TZ_KNOWN, sizeof(PARAM_TZ_KNOWN) - 1U, q.TzKnown); + TimeQualitySd_FormatBoolParam(formatter, PARAM_IS_SYNCED, sizeof(PARAM_IS_SYNCED) - 1U, q.IsSynced); TimeQualitySd_FormatSyncAccuracy(formatter, q.SyncAccuracyMicroseconds); SolidSyslogFormatter_AsciiCharacter(formatter, ']'); } @@ -76,7 +76,7 @@ static inline void TimeQualitySd_FormatSyncAccuracy(struct SolidSyslogFormatter* { if (value != SOLIDSYSLOG_SYNC_ACCURACY_OMIT) { - SolidSyslogFormatter_BoundedString(formatter, PARAM_SYNC_ACCURACY, sizeof(PARAM_SYNC_ACCURACY) - 1); + SolidSyslogFormatter_BoundedString(formatter, PARAM_SYNC_ACCURACY, sizeof(PARAM_SYNC_ACCURACY) - 1U); SolidSyslogFormatter_Uint32(formatter, value); SolidSyslogFormatter_AsciiCharacter(formatter, '"'); } diff --git a/Core/Source/SolidSyslogUdpPayload.c b/Core/Source/SolidSyslogUdpPayload.c index 9a88f421..3406a34e 100644 --- a/Core/Source/SolidSyslogUdpPayload.c +++ b/Core/Source/SolidSyslogUdpPayload.c @@ -3,9 +3,9 @@ enum { - IPV4_HEADER_BYTES = 20, - IPV6_HEADER_BYTES = 40, - UDP_HEADER_BYTES = 8 + IPV4_HEADER_BYTES = 20U, + IPV6_HEADER_BYTES = 40U, + UDP_HEADER_BYTES = 8U }; static inline size_t UdpPayload_FindLastCodepointStart(const uint8_t* buffer, size_t length); @@ -19,12 +19,12 @@ static inline size_t UdpPayload_ExpectedSequenceLength(uint8_t startByte); size_t SolidSyslogUdpPayload_FromMtu(size_t mtu, bool isIpv6) { size_t overhead = (isIpv6 ? IPV6_HEADER_BYTES : IPV4_HEADER_BYTES) + UDP_HEADER_BYTES; - return mtu > overhead ? mtu - overhead : 0; + return mtu > overhead ? mtu - overhead : 0U; } size_t SolidSyslogUdpPayload_TrimToCodepointBoundary(const uint8_t* buffer, size_t length) { - if (length > 0) + if (length > 0U) { size_t lastCodepointStart = UdpPayload_FindLastCodepointStart(buffer, length); if (UdpPayload_LastCodepointExtendsPastCut(buffer, length, lastCodepointStart)) @@ -37,8 +37,8 @@ size_t SolidSyslogUdpPayload_TrimToCodepointBoundary(const uint8_t* buffer, size static inline size_t UdpPayload_FindLastCodepointStart(const uint8_t* buffer, size_t length) { - size_t startIndex = length - 1; - while (startIndex > 0 && SolidSyslogUtf8_IsContinuationByte((char) buffer[startIndex])) + size_t startIndex = length - 1U; + while ((startIndex > 0U) && SolidSyslogUtf8_IsContinuationByte((char) buffer[startIndex])) { startIndex--; } @@ -59,22 +59,22 @@ static inline bool UdpPayload_LastCodepointExtendsPastCut( static inline size_t UdpPayload_ExpectedSequenceLength(uint8_t startByte) { char b = (char) startByte; - size_t length = 0; + size_t length = 0U; if (SolidSyslogUtf8_IsAsciiByte(b)) { - length = 1; + length = 1U; } else if (SolidSyslogUtf8_IsTwoByteLead(b)) { - length = 2; + length = 2U; } else if (SolidSyslogUtf8_IsThreeByteLead(b)) { - length = 3; + length = 3U; } else { - length = 4; + length = 4U; } return length; } diff --git a/Core/Source/SolidSyslogUdpSender.c b/Core/Source/SolidSyslogUdpSender.c index 692dbc10..f43c79fe 100644 --- a/Core/Source/SolidSyslogUdpSender.c +++ b/Core/Source/SolidSyslogUdpSender.c @@ -247,7 +247,7 @@ static inline enum SolidSyslogDatagramSendResult UdpSender_RetryAfterOversize( /* Default SENT swallows trimmed == 0 (path can't carry the message) so the * Service algorithm doesn't loop on an undeliverable. */ enum SolidSyslogDatagramSendResult result = SolidSyslogDatagramSendResult_Sent; - if (trimmed > 0) + if (trimmed > 0U) { result = SolidSyslogDatagram_SendTo(udp->Config.Datagram, buffer, trimmed, UdpSender_Address(udp)); if (result == SolidSyslogDatagramSendResult_Oversize) diff --git a/Platform/FatFs/Interface/SolidSyslogFatFsFile.h b/Platform/FatFs/Interface/SolidSyslogFatFsFile.h index 17f2d162..0430b5d0 100644 --- a/Platform/FatFs/Interface/SolidSyslogFatFsFile.h +++ b/Platform/FatFs/Interface/SolidSyslogFatFsFile.h @@ -18,12 +18,12 @@ EXTERN_C_BEGIN * makes this overridable via the tunables mechanism. */ enum { - SOLIDSYSLOG_FATFS_FILE_SIZE = sizeof(intptr_t) * 180 + SOLIDSYSLOG_FATFS_FILE_SIZE = sizeof(intptr_t) * 180U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_FATFS_FILE_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_FATFS_FILE_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogFatFsFileStorage; struct SolidSyslogFile* SolidSyslogFatFsFile_Create(SolidSyslogFatFsFileStorage * storage); diff --git a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosDatagram.h b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosDatagram.h index d206044b..a7dba9ce 100644 --- a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosDatagram.h +++ b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosDatagram.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_FREERTOSDATAGRAM_SIZE = sizeof(intptr_t) * 8 + SOLIDSYSLOG_FREERTOSDATAGRAM_SIZE = sizeof(intptr_t) * 8U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_FREERTOSDATAGRAM_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_FREERTOSDATAGRAM_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogFreeRtosDatagramStorage; struct SolidSyslogDatagram* SolidSyslogFreeRtosDatagram_Create(SolidSyslogFreeRtosDatagramStorage * storage); diff --git a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosMutex.h b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosMutex.h index 0a247481..4e509d37 100644 --- a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosMutex.h +++ b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosMutex.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_FREERTOSMUTEX_SIZE = sizeof(intptr_t) * 20 + SOLIDSYSLOG_FREERTOSMUTEX_SIZE = sizeof(intptr_t) * 20U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_FREERTOSMUTEX_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_FREERTOSMUTEX_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogFreeRtosMutexStorage; struct SolidSyslogMutex* SolidSyslogFreeRtosMutex_Create(SolidSyslogFreeRtosMutexStorage * storage); diff --git a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosStaticResolver.h b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosStaticResolver.h index 3c014057..c7853b75 100644 --- a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosStaticResolver.h +++ b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosStaticResolver.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_FREERTOSSTATICRESOLVER_SIZE = sizeof(intptr_t) * 4 + SOLIDSYSLOG_FREERTOSSTATICRESOLVER_SIZE = sizeof(intptr_t) * 4U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_FREERTOSSTATICRESOLVER_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_FREERTOSSTATICRESOLVER_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogFreeRtosStaticResolverStorage; struct SolidSyslogResolver* SolidSyslogFreeRtosStaticResolver_Create( diff --git a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosTcpStream.h b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosTcpStream.h index 1ce1a64d..434f4734 100644 --- a/Platform/FreeRtos/Interface/SolidSyslogFreeRtosTcpStream.h +++ b/Platform/FreeRtos/Interface/SolidSyslogFreeRtosTcpStream.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_FREERTOSTCPSTREAM_SIZE = sizeof(intptr_t) * 8 + SOLIDSYSLOG_FREERTOSTCPSTREAM_SIZE = sizeof(intptr_t) * 8U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_FREERTOSTCPSTREAM_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_FREERTOSTCPSTREAM_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogFreeRtosTcpStreamStorage; struct SolidSyslogStream* SolidSyslogFreeRtosTcpStream_Create(SolidSyslogFreeRtosTcpStreamStorage * storage); diff --git a/Platform/OpenSsl/Interface/SolidSyslogTlsStream.h b/Platform/OpenSsl/Interface/SolidSyslogTlsStream.h index 289d617f..2b992adb 100644 --- a/Platform/OpenSsl/Interface/SolidSyslogTlsStream.h +++ b/Platform/OpenSsl/Interface/SolidSyslogTlsStream.h @@ -12,12 +12,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_TLS_STREAM_SIZE = sizeof(intptr_t) * 14 + SOLIDSYSLOG_TLS_STREAM_SIZE = sizeof(intptr_t) * 14U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_TLS_STREAM_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_TLS_STREAM_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogTlsStreamStorage; struct SolidSyslogTlsStreamConfig diff --git a/Platform/Posix/Interface/SolidSyslogPosixFile.h b/Platform/Posix/Interface/SolidSyslogPosixFile.h index ac472925..b676bc44 100644 --- a/Platform/Posix/Interface/SolidSyslogPosixFile.h +++ b/Platform/Posix/Interface/SolidSyslogPosixFile.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_POSIX_FILE_SIZE = sizeof(intptr_t) * 11 + SOLIDSYSLOG_POSIX_FILE_SIZE = sizeof(intptr_t) * 11U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_POSIX_FILE_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_POSIX_FILE_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogPosixFileStorage; struct SolidSyslogFile* SolidSyslogPosixFile_Create(SolidSyslogPosixFileStorage * storage); diff --git a/Platform/Posix/Interface/SolidSyslogPosixMutex.h b/Platform/Posix/Interface/SolidSyslogPosixMutex.h index e1d787e3..0eb643bd 100644 --- a/Platform/Posix/Interface/SolidSyslogPosixMutex.h +++ b/Platform/Posix/Interface/SolidSyslogPosixMutex.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_POSIXMUTEX_SIZE = sizeof(intptr_t) * 10 + SOLIDSYSLOG_POSIXMUTEX_SIZE = sizeof(intptr_t) * 10U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_POSIXMUTEX_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_POSIXMUTEX_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogPosixMutexStorage; struct SolidSyslogMutex* SolidSyslogPosixMutex_Create(SolidSyslogPosixMutexStorage * storage); diff --git a/Platform/Posix/Interface/SolidSyslogPosixTcpStream.h b/Platform/Posix/Interface/SolidSyslogPosixTcpStream.h index 07e16807..2278d58b 100644 --- a/Platform/Posix/Interface/SolidSyslogPosixTcpStream.h +++ b/Platform/Posix/Interface/SolidSyslogPosixTcpStream.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_POSIX_TCP_STREAM_SIZE = sizeof(intptr_t) * 5 + SOLIDSYSLOG_POSIX_TCP_STREAM_SIZE = sizeof(intptr_t) * 5U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_POSIX_TCP_STREAM_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_POSIX_TCP_STREAM_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogPosixTcpStreamStorage; struct SolidSyslogStream* SolidSyslogPosixTcpStream_Create(SolidSyslogPosixTcpStreamStorage * storage); diff --git a/Platform/Posix/Source/SolidSyslogPosixFile.c b/Platform/Posix/Source/SolidSyslogPosixFile.c index 55bd715f..3ccb1acf 100644 --- a/Platform/Posix/Source/SolidSyslogPosixFile.c +++ b/Platform/Posix/Source/SolidSyslogPosixFile.c @@ -124,7 +124,7 @@ static size_t PosixFile_Size(struct SolidSyslogFile* self) { struct SolidSyslogPosixFile* posix = (struct SolidSyslogPosixFile*) self; off_t size = lseek(posix->Fd, 0, SEEK_END); - return (size >= 0) ? (size_t) size : 0; + return (size >= 0) ? (size_t) size : 0U; } static void PosixFile_Truncate(struct SolidSyslogFile* self) diff --git a/Platform/Posix/Source/SolidSyslogPosixHostname.c b/Platform/Posix/Source/SolidSyslogPosixHostname.c index dfaaf7c1..3a7357d1 100644 --- a/Platform/Posix/Source/SolidSyslogPosixHostname.c +++ b/Platform/Posix/Source/SolidSyslogPosixHostname.c @@ -8,7 +8,7 @@ struct SolidSyslogFormatter; enum { - MAX_HOSTNAME_SIZE = 256 + MAX_HOSTNAME_SIZE = 256U }; void SolidSyslogPosixHostname_Get(struct SolidSyslogFormatter* formatter) @@ -17,7 +17,7 @@ void SolidSyslogPosixHostname_Get(struct SolidSyslogFormatter* formatter) if (gethostname(hostname, sizeof(hostname)) == 0) { - hostname[sizeof(hostname) - 1] = '\0'; + hostname[sizeof(hostname) - 1U] = '\0'; SolidSyslogFormatter_PrintUsAsciiString(formatter, hostname, sizeof(hostname)); } } diff --git a/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c b/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c index c3e93484..39e251fc 100644 --- a/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c +++ b/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c @@ -40,7 +40,7 @@ struct SolidSyslogBuffer* SolidSyslogPosixMessageQueueBuffer_Create(size_t maxMe instance = (struct SolidSyslogPosixMessageQueueBuffer) {0}; struct SolidSyslogFormatter* name = SolidSyslogFormatter_Create(instance.NameStorage, MAX_NAME_SIZE); - SolidSyslogFormatter_BoundedString(name, QUEUE_NAME_PREFIX, sizeof(QUEUE_NAME_PREFIX) - 1); + SolidSyslogFormatter_BoundedString(name, QUEUE_NAME_PREFIX, sizeof(QUEUE_NAME_PREFIX) - 1U); SolidSyslogPosixProcessId_Get(name); struct mq_attr attr = {0}; @@ -68,7 +68,7 @@ static bool PosixMessageQueueBuffer_Read(struct SolidSyslogBuffer* self, void* d ssize_t received = mq_receive(mqBuffer->Mq, data, maxSize, NULL); bool success = received >= 0; - *bytesRead = success ? (size_t) received : 0; + *bytesRead = success ? (size_t) received : 0U; return success; } diff --git a/Platform/Windows/Interface/SolidSyslogWindowsFile.h b/Platform/Windows/Interface/SolidSyslogWindowsFile.h index 2e5416d9..97a00380 100644 --- a/Platform/Windows/Interface/SolidSyslogWindowsFile.h +++ b/Platform/Windows/Interface/SolidSyslogWindowsFile.h @@ -9,12 +9,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_WINDOWS_FILE_SIZE = sizeof(intptr_t) * 11 + SOLIDSYSLOG_WINDOWS_FILE_SIZE = sizeof(intptr_t) * 11U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_WINDOWS_FILE_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_WINDOWS_FILE_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogWindowsFileStorage; struct SolidSyslogFile* SolidSyslogWindowsFile_Create(SolidSyslogWindowsFileStorage * storage); diff --git a/Platform/Windows/Interface/SolidSyslogWindowsMutex.h b/Platform/Windows/Interface/SolidSyslogWindowsMutex.h index 41029c02..b933b240 100644 --- a/Platform/Windows/Interface/SolidSyslogWindowsMutex.h +++ b/Platform/Windows/Interface/SolidSyslogWindowsMutex.h @@ -11,12 +11,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_WINDOWSMUTEX_SIZE = sizeof(intptr_t) * 10 + SOLIDSYSLOG_WINDOWSMUTEX_SIZE = sizeof(intptr_t) * 10U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_WINDOWSMUTEX_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_WINDOWSMUTEX_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogWindowsMutexStorage; struct SolidSyslogMutex* SolidSyslogWindowsMutex_Create(SolidSyslogWindowsMutexStorage * storage); diff --git a/Platform/Windows/Interface/SolidSyslogWinsockTcpStream.h b/Platform/Windows/Interface/SolidSyslogWinsockTcpStream.h index 5c05937e..8d39dd15 100644 --- a/Platform/Windows/Interface/SolidSyslogWinsockTcpStream.h +++ b/Platform/Windows/Interface/SolidSyslogWinsockTcpStream.h @@ -9,12 +9,12 @@ EXTERN_C_BEGIN enum { - SOLIDSYSLOG_WINSOCK_TCP_STREAM_SIZE = sizeof(intptr_t) * 5 + SOLIDSYSLOG_WINSOCK_TCP_STREAM_SIZE = sizeof(intptr_t) * 5U }; typedef struct { - intptr_t slots[(SOLIDSYSLOG_WINSOCK_TCP_STREAM_SIZE + sizeof(intptr_t) - 1) / sizeof(intptr_t)]; + intptr_t slots[(SOLIDSYSLOG_WINSOCK_TCP_STREAM_SIZE + sizeof(intptr_t) - 1U) / sizeof(intptr_t)]; } SolidSyslogWinsockTcpStreamStorage; /* Precondition: caller has invoked WSAStartup() before using the stream, diff --git a/Platform/Windows/Source/SolidSyslogWindowsFile.c b/Platform/Windows/Source/SolidSyslogWindowsFile.c index cbbd2f6f..f09c6491 100644 --- a/Platform/Windows/Source/SolidSyslogWindowsFile.c +++ b/Platform/Windows/Source/SolidSyslogWindowsFile.c @@ -136,7 +136,7 @@ static size_t WindowsFile_Size(struct SolidSyslogFile* self) { struct SolidSyslogWindowsFile* windows = (struct SolidSyslogWindowsFile*) self; __int64 size = _lseeki64(windows->Fd, 0, SEEK_END); - return (size >= 0) ? (size_t) size : 0; + return (size >= 0) ? (size_t) size : 0U; } static void WindowsFile_Truncate(struct SolidSyslogFile* self) diff --git a/Platform/Windows/Source/SolidSyslogWindowsHostname.c b/Platform/Windows/Source/SolidSyslogWindowsHostname.c index 1980305b..e9136832 100644 --- a/Platform/Windows/Source/SolidSyslogWindowsHostname.c +++ b/Platform/Windows/Source/SolidSyslogWindowsHostname.c @@ -17,7 +17,7 @@ static BOOL WINAPI WindowsHostname_CallGetComputerNameExA(COMPUTER_NAME_FORMAT n enum { - MAX_HOSTNAME_SIZE = 256 + MAX_HOSTNAME_SIZE = 256U }; void SolidSyslogWindowsHostname_Get(struct SolidSyslogFormatter* formatter) @@ -27,7 +27,7 @@ void SolidSyslogWindowsHostname_Get(struct SolidSyslogFormatter* formatter) if (WindowsHostname_GetComputerNameExA(ComputerNamePhysicalDnsHostname, hostname, &size)) { - hostname[sizeof(hostname) - 1] = '\0'; + hostname[sizeof(hostname) - 1U] = '\0'; SolidSyslogFormatter_PrintUsAsciiString(formatter, hostname, sizeof(hostname)); } } From f22d99a18bafbbd9c9534dda538290008407ebaf Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 07:40:06 +0100 Subject: [PATCH 03/12] refactor: S10.10 fix MISRA 10.1 essential-type mismatches in byte operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bitwise operators (& == << ^=) on plain char are inappropriate per MISRA Rule 10.1 — chars are essentially-character, the bitwise operators require essentially-unsigned operands. Cast char operands to unsigned char and U-suffix the hex literal masks they are tested against. Affected sites: - Core/Source/SolidSyslogUtf8.h: five top-bit classifiers (IsAsciiByte, IsContinuationByte, IsTwoByteLead, IsThreeByteLead, IsFourByteLead). - Core/Source/SolidSyslogFormatter.c: IsOverlongTwoByteLead, IsOverlongThreeByteEncoding, IsUtf16SurrogateEncoding, IsOverlongFourByteEncoding, IsAboveUnicodeMaxEncoding. - Core/Source/SolidSyslogCrc16.c: the data-byte shift inside SolidSyslogCrc16_Compute now uses a literal 8U (the BITS_PER_BYTE anonymous-enum constant remained essentially-signed for cppcheck-misra even after U-suffixing the initializer); the unrelated enum initializers picked up matching U suffixes for visual consistency inside the same block. cppcheck-misra: rule 10.1 findings 11 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Source/SolidSyslogCrc16.c | 10 +++++----- Core/Source/SolidSyslogFormatter.c | 10 +++++----- Core/Source/SolidSyslogUtf8.h | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Core/Source/SolidSyslogCrc16.c b/Core/Source/SolidSyslogCrc16.c index 77d12f8a..d6607e3a 100644 --- a/Core/Source/SolidSyslogCrc16.c +++ b/Core/Source/SolidSyslogCrc16.c @@ -10,10 +10,10 @@ enum { - CRC16_CCITT_INIT = 0xFFFF, - CRC16_CCITT_POLY = 0x1021, - BITS_PER_BYTE = 8, - MSB_MASK = 0x8000 + CRC16_CCITT_INIT = 0xFFFFU, + CRC16_CCITT_POLY = 0x1021U, + BITS_PER_BYTE = 8U, + MSB_MASK = 0x8000U }; uint16_t SolidSyslogCrc16_Compute(const uint8_t* data, uint16_t length) @@ -22,7 +22,7 @@ uint16_t SolidSyslogCrc16_Compute(const uint8_t* data, uint16_t length) for (uint16_t i = 0; i < length; i++) { - crc ^= (uint16_t) ((uint16_t) data[i] << BITS_PER_BYTE); + crc ^= (uint16_t) ((uint16_t) data[i] << 8U); for (int bit = 0; bit < BITS_PER_BYTE; bit++) { diff --git a/Core/Source/SolidSyslogFormatter.c b/Core/Source/SolidSyslogFormatter.c index d8bf9ef2..12daf35e 100644 --- a/Core/Source/SolidSyslogFormatter.c +++ b/Core/Source/SolidSyslogFormatter.c @@ -219,7 +219,7 @@ static inline bool Formatter_IsValidUtf8TwoByte(char lead, char continuation1) static inline bool Formatter_IsOverlongTwoByteLead(char byte) { - return (byte & 0xFE) == 0xC0; + return ((unsigned char) byte & 0xFEU) == 0xC0U; } static inline bool Formatter_IsValidUtf8ThreeByte(char lead, char continuation1, char continuation2) @@ -232,12 +232,12 @@ static inline bool Formatter_IsValidUtf8ThreeByte(char lead, char continuation1, static inline bool Formatter_IsOverlongThreeByteEncoding(char lead, char continuation1) { - return (lead == '\xE0') && ((continuation1 & 0xE0) == 0x80); + return ((unsigned char) lead == 0xE0U) && (((unsigned char) continuation1 & 0xE0U) == 0x80U); } static inline bool Formatter_IsUtf16SurrogateEncoding(char lead, char continuation1) { - return (lead == '\xED') && ((continuation1 & 0xE0) == 0xA0); + return ((unsigned char) lead == 0xEDU) && (((unsigned char) continuation1 & 0xE0U) == 0xA0U); } static inline bool Formatter_IsValidUtf8FourByte(char lead, char continuation1, char continuation2, char continuation3) @@ -250,13 +250,13 @@ static inline bool Formatter_IsValidUtf8FourByte(char lead, char continuation1, static inline bool Formatter_IsOverlongFourByteEncoding(char lead, char continuation1) { - return (lead == '\xF0') && ((continuation1 & 0xF0) == 0x80); + return ((unsigned char) lead == 0xF0U) && (((unsigned char) continuation1 & 0xF0U) == 0x80U); } static inline bool Formatter_IsAboveUnicodeMaxEncoding(char lead, char continuation1) { - bool f4WithCont1Above8F = (lead == '\xF4') && ((continuation1 & 0xF0) != 0x80); unsigned char uLead = (unsigned char) lead; + bool f4WithCont1Above8F = (uLead == 0xF4U) && (((unsigned char) continuation1 & 0xF0U) != 0x80U); bool f5OrHigherLead = (uLead >= 0xF5U) && (uLead <= 0xF7U); return f4WithCont1Above8F || f5OrHigherLead; } diff --git a/Core/Source/SolidSyslogUtf8.h b/Core/Source/SolidSyslogUtf8.h index 60e1c9bc..097b2307 100644 --- a/Core/Source/SolidSyslogUtf8.h +++ b/Core/Source/SolidSyslogUtf8.h @@ -13,27 +13,27 @@ EXTERN_C_BEGIN static inline bool SolidSyslogUtf8_IsAsciiByte(char byte) { - return (byte & 0x80) == 0; + return ((unsigned char) byte & 0x80U) == 0U; } static inline bool SolidSyslogUtf8_IsContinuationByte(char byte) { - return (byte & 0xC0) == 0x80; + return ((unsigned char) byte & 0xC0U) == 0x80U; } static inline bool SolidSyslogUtf8_IsTwoByteLead(char byte) { - return (byte & 0xE0) == 0xC0; + return ((unsigned char) byte & 0xE0U) == 0xC0U; } static inline bool SolidSyslogUtf8_IsThreeByteLead(char byte) { - return (byte & 0xF0) == 0xE0; + return ((unsigned char) byte & 0xF0U) == 0xE0U; } static inline bool SolidSyslogUtf8_IsFourByteLead(char byte) { - return (byte & 0xF8) == 0xF0; + return ((unsigned char) byte & 0xF8U) == 0xF0U; } EXTERN_C_END From d76cc19f55277475863725c27ad2dfb9c278e8f3 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 15:40:15 +0100 Subject: [PATCH 04/12] refactor: S10.10 add trailing else to terminate if/else-if chains (MISRA 15.7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add empty else clauses with explanatory comments to ten if/else-if chains spanning Core/Source/ and Platform/*/Source/. The else bodies hold no code — they document the residual case the existing branches do not cover, which is what Rule 15.7 asks for. cppcheck-misra: rule 15.7 findings 10 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Source/BlockSequence.c | 12 ++++++++++++ Core/Source/SolidSyslogFormatter.c | 8 ++++++++ Platform/OpenSsl/Source/SolidSyslogTlsStream.c | 4 ++++ Platform/Posix/Source/SolidSyslogPosixDatagram.c | 4 ++++ Platform/Posix/Source/SolidSyslogPosixTcpStream.c | 4 ++++ Platform/Windows/Source/SolidSyslogWinsockDatagram.c | 4 ++++ .../Windows/Source/SolidSyslogWinsockTcpStream.c | 4 ++++ 7 files changed, 40 insertions(+) diff --git a/Core/Source/BlockSequence.c b/Core/Source/BlockSequence.c index dd051506..500606ca 100644 --- a/Core/Source/BlockSequence.c +++ b/Core/Source/BlockSequence.c @@ -151,6 +151,10 @@ static void BlockSequence_ScanForBlockPresence(struct BlockSequence* blockSequen presence->FirstAbsent = seq; presence->FoundAbsent = true; } + else + { + /* present run already closed — nothing to record */ + } } } @@ -208,6 +212,10 @@ bool BlockSequence_PrepareForWrite(struct BlockSequence* blockSequence, size_t r { spaceAvailable = BlockSequence_RotateToNextBlock(blockSequence, readBlockChanged); } + else + { + /* current block has room — leave spaceAvailable=true */ + } return spaceAvailable; } @@ -369,6 +377,10 @@ static inline void BlockSequence_NotifyThresholdCrossed(struct BlockSequence* bl blockSequence->ThresholdCrossed = true; blockSequence->OnThresholdCrossed(blockSequence->ThresholdContext); } + else + { + /* still above threshold and already notified — no edge to report */ + } } } diff --git a/Core/Source/SolidSyslogFormatter.c b/Core/Source/SolidSyslogFormatter.c index 12daf35e..ead32257 100644 --- a/Core/Source/SolidSyslogFormatter.c +++ b/Core/Source/SolidSyslogFormatter.c @@ -207,6 +207,10 @@ static inline size_t Formatter_Utf8CodepointLength(const char* source) { length = 4; } + else + { + /* lead does not start a valid 1-/2-/3-/4-byte UTF-8 sequence — length stays 0 */ + } return length; } @@ -505,6 +509,10 @@ static inline void Formatter_TrimTruncatedMultiByteTail(struct SolidSyslogFormat { trimFrom = p - 3U; } + else + { + /* tail does not look like a truncated multi-byte sequence — trim nothing */ + } for (size_t i = trimFrom; i < p; i++) { buffer[i] = '\0'; diff --git a/Platform/OpenSsl/Source/SolidSyslogTlsStream.c b/Platform/OpenSsl/Source/SolidSyslogTlsStream.c index 2c00c1ed..3963f8d2 100644 --- a/Platform/OpenSsl/Source/SolidSyslogTlsStream.c +++ b/Platform/OpenSsl/Source/SolidSyslogTlsStream.c @@ -177,6 +177,10 @@ static inline bool TlsStream_ConfigureClientIdentity(SSL_CTX* ctx, const struct (SSL_CTX_use_PrivateKey_file(ctx, config->ClientKeyPath, SSL_FILETYPE_PEM) == 1) && (SSL_CTX_check_private_key(ctx) == 1); } + else + { + /* neither cert nor key supplied — server-auth-only TLS, ok stays true */ + } return ok; } diff --git a/Platform/Posix/Source/SolidSyslogPosixDatagram.c b/Platform/Posix/Source/SolidSyslogPosixDatagram.c index 2e12784a..11cf9c88 100644 --- a/Platform/Posix/Source/SolidSyslogPosixDatagram.c +++ b/Platform/Posix/Source/SolidSyslogPosixDatagram.c @@ -95,6 +95,10 @@ static enum SolidSyslogDatagramSendResult PosixDatagram_SendTo( { result = SolidSyslogDatagramSendResult_Oversize; } + else + { + /* generic send failure — result stays Failed */ + } } return result; } diff --git a/Platform/Posix/Source/SolidSyslogPosixTcpStream.c b/Platform/Posix/Source/SolidSyslogPosixTcpStream.c index f737cac4..3fd6f100 100644 --- a/Platform/Posix/Source/SolidSyslogPosixTcpStream.c +++ b/Platform/Posix/Source/SolidSyslogPosixTcpStream.c @@ -197,6 +197,10 @@ static bool PosixTcpStream_Connect(int fd, const struct sockaddr_in* sin) { connected = PosixTcpStream_WaitForConnectCompletion(fd) && PosixTcpStream_ReadDeferredConnectError(fd); } + else + { + /* immediate fail-fast (refused, unreachable, etc.) — connected stays false */ + } return connected; } diff --git a/Platform/Windows/Source/SolidSyslogWinsockDatagram.c b/Platform/Windows/Source/SolidSyslogWinsockDatagram.c index 66bc9b07..b233522f 100644 --- a/Platform/Windows/Source/SolidSyslogWinsockDatagram.c +++ b/Platform/Windows/Source/SolidSyslogWinsockDatagram.c @@ -140,6 +140,10 @@ static enum SolidSyslogDatagramSendResult WinsockDatagram_SendTo( { result = SolidSyslogDatagramSendResult_Oversize; } + else + { + /* generic send failure — result stays Failed */ + } } return result; } diff --git a/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c b/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c index 467044c4..bd30db03 100644 --- a/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c +++ b/Platform/Windows/Source/SolidSyslogWinsockTcpStream.c @@ -265,6 +265,10 @@ static bool WinsockTcpStream_Connect(SOCKET fd, const struct sockaddr_in* sin) { connected = WinsockTcpStream_WaitForConnectCompletion(fd) && WinsockTcpStream_ReadDeferredConnectError(fd); } + else + { + /* immediate fail-fast (refused, unreachable, etc.) — connected stays false */ + } return connected; } From 84ad4ed2024e30c65f4121bf5c5ca5b0cf9be09c Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 15:44:08 +0100 Subject: [PATCH 05/12] refactor: S10.10 add explicit precedence parentheses (MISRA 12.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add parentheses around sub-expressions mixing comparison/equality with arithmetic or logical operators to make precedence explicit per MISRA Rule 12.1 (advisory). One ternary in SolidSyslogUdpPayload_FromMtu refactored to a small if/return — cppcheck-misra continued to flag the return-of-ternary form even after bracketing both arms. cppcheck-misra: rule 12.1 findings 5 → 0 (audit baseline; +3 newly surfaced sites that fell out of the 10.4 sweep were swept along). Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Source/SolidSyslogAtomicCounter.c | 2 +- Core/Source/SolidSyslogCircularBuffer.c | 6 +++--- Core/Source/SolidSyslogFormatter.c | 4 ++-- Core/Source/SolidSyslogUdpPayload.c | 7 ++++++- Platform/OpenSsl/Source/SolidSyslogTlsStream.c | 2 +- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Core/Source/SolidSyslogAtomicCounter.c b/Core/Source/SolidSyslogAtomicCounter.c index 29289af0..2dc01df4 100644 --- a/Core/Source/SolidSyslogAtomicCounter.c +++ b/Core/Source/SolidSyslogAtomicCounter.c @@ -20,7 +20,7 @@ static struct SolidSyslogAtomicCounter instance; static inline uint32_t AtomicCounter_NextSequenceId(uint32_t current) { - return (current >= SEQUENCE_ID_MAX) ? 1U : current + 1U; + return (current >= SEQUENCE_ID_MAX) ? 1U : (current + 1U); } static inline bool AtomicCounter_TryAdvance(struct SolidSyslogAtomicU32* slot, uint32_t* nextOut) diff --git a/Core/Source/SolidSyslogCircularBuffer.c b/Core/Source/SolidSyslogCircularBuffer.c index 7eed6f0d..e2d27ad2 100644 --- a/Core/Source/SolidSyslogCircularBuffer.c +++ b/Core/Source/SolidSyslogCircularBuffer.c @@ -174,9 +174,9 @@ static inline bool CircularBuffer_RecordFitsAtTail(const struct SolidSyslogCircu { if (CircularBuffer_IsWrapped(circular)) { - return circular->Tail + recordBytes < circular->Head; + return (circular->Tail + recordBytes) < circular->Head; } - return circular->Tail + recordBytes <= circular->Capacity; + return (circular->Tail + recordBytes) <= circular->Capacity; } static inline bool CircularBuffer_RecordFitsAfterWrap( @@ -184,7 +184,7 @@ static inline bool CircularBuffer_RecordFitsAfterWrap( size_t recordBytes ) { - return (!CircularBuffer_IsWrapped(circular)) && recordBytes < circular->Head; + return (!CircularBuffer_IsWrapped(circular)) && (recordBytes < circular->Head); } static inline void CircularBuffer_ResetToStart(struct SolidSyslogCircularBuffer* circular) diff --git a/Core/Source/SolidSyslogFormatter.c b/Core/Source/SolidSyslogFormatter.c index ead32257..676bfcc7 100644 --- a/Core/Source/SolidSyslogFormatter.c +++ b/Core/Source/SolidSyslogFormatter.c @@ -137,7 +137,7 @@ static inline void Formatter_WriteChar(struct SolidSyslogFormatter* formatter, c static inline bool Formatter_HasCapacity(const struct SolidSyslogFormatter* formatter) { - return (formatter->Size > 0U) && (formatter->Position < formatter->Size - 1U); + return (formatter->Size > 0U) && (formatter->Position < (formatter->Size - 1U)); } /* @@ -325,7 +325,7 @@ static inline void Formatter_WriteEscaped(struct EscapedContext* context) static inline bool Formatter_Fits(const struct EscapedContext* context, size_t decodedAdvance) { - return (decodedAdvance > 0U) && (decodedAdvance <= context->MaxDecodedLength - context->DecodedLength); + return (decodedAdvance > 0U) && (decodedAdvance <= (context->MaxDecodedLength - context->DecodedLength)); } /* NOLINTBEGIN(bugprone-easily-swappable-parameters) -- see forward declaration */ diff --git a/Core/Source/SolidSyslogUdpPayload.c b/Core/Source/SolidSyslogUdpPayload.c index 3406a34e..180551a7 100644 --- a/Core/Source/SolidSyslogUdpPayload.c +++ b/Core/Source/SolidSyslogUdpPayload.c @@ -19,7 +19,12 @@ static inline size_t UdpPayload_ExpectedSequenceLength(uint8_t startByte); size_t SolidSyslogUdpPayload_FromMtu(size_t mtu, bool isIpv6) { size_t overhead = (isIpv6 ? IPV6_HEADER_BYTES : IPV4_HEADER_BYTES) + UDP_HEADER_BYTES; - return mtu > overhead ? mtu - overhead : 0U; + size_t payload = 0U; + if (mtu > overhead) + { + payload = mtu - overhead; + } + return payload; } size_t SolidSyslogUdpPayload_TrimToCodepointBoundary(const uint8_t* buffer, size_t length) diff --git a/Platform/OpenSsl/Source/SolidSyslogTlsStream.c b/Platform/OpenSsl/Source/SolidSyslogTlsStream.c index 3963f8d2..47cc8ed8 100644 --- a/Platform/OpenSsl/Source/SolidSyslogTlsStream.c +++ b/Platform/OpenSsl/Source/SolidSyslogTlsStream.c @@ -147,7 +147,7 @@ static inline bool TlsStream_InitSslContext(struct SolidSyslogTlsStream* stream) static inline SSL_CTX* TlsStream_CreateSslContext(const struct SolidSyslogTlsStreamConfig* config) { SSL_CTX* ctx = SSL_CTX_new(TLS_client_method()); - if (ctx != NULL && !TlsStream_ConfigureSslContext(ctx, config)) + if ((ctx != NULL) && !TlsStream_ConfigureSslContext(ctx, config)) { SSL_CTX_free(ctx); ctx = NULL; From 4599c1e999806364d39531886b4fc46baf304f5a Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 15:47:22 +0100 Subject: [PATCH 06/12] refactor: S10.10 hoist composite-cast in UTC offset formatter (MISRA 10.8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cast absoluteMinutes to uint32_t once at the top of SolidSyslog_FormatNonZeroUtcOffset and use uint32_t arithmetic for the hours/minutes split. Previous form cast each composite (absoluteMinutes / 60) and (absoluteMinutes % 60) — a different essential-type category on a composite expression, which violates MISRA Rule 10.8. cppcheck-misra: rule 10.8 findings 2 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Source/SolidSyslog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/Source/SolidSyslog.c b/Core/Source/SolidSyslog.c index 36a72e8c..e29d7e2e 100644 --- a/Core/Source/SolidSyslog.c +++ b/Core/Source/SolidSyslog.c @@ -447,12 +447,12 @@ static inline void SolidSyslog_FormatUtcOffset(struct SolidSyslogFormatter* f, i static inline void SolidSyslog_FormatNonZeroUtcOffset(struct SolidSyslogFormatter* f, int16_t offsetMinutes) { - int16_t absoluteMinutes = SolidSyslog_AbsoluteInt16(offsetMinutes); + uint32_t absoluteMinutes = (uint32_t) SolidSyslog_AbsoluteInt16(offsetMinutes); SolidSyslogFormatter_AsciiCharacter(f, (offsetMinutes > 0) ? '+' : '-'); - SolidSyslogFormatter_TwoDigit(f, (uint32_t) (absoluteMinutes / 60)); + SolidSyslogFormatter_TwoDigit(f, absoluteMinutes / 60U); SolidSyslogFormatter_AsciiCharacter(f, ':'); - SolidSyslogFormatter_TwoDigit(f, (uint32_t) (absoluteMinutes % 60)); + SolidSyslogFormatter_TwoDigit(f, absoluteMinutes % 60U); } static inline int16_t SolidSyslog_AbsoluteInt16(int16_t value) From 1a3e3424d6ecc34c9f80f87b524fcc56d1aee3ca Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 15:49:12 +0100 Subject: [PATCH 07/12] refactor: S10.10 inline-suppress MISRA 2.5 on public CircularBuffer macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE[_BYTES] macros are part of the public API: integrator code under Tests/ and Bdd/Targets/ calls them to size caller-supplied storage. cppcheck-misra runs only over Core/Source/ + Platform/*/Source/, so from its scope the macros look unused. Annotate with an inline `cppcheck-suppress misra-c2012-2.5` naming the consumers, so the rule keeps catching genuinely-unused macros elsewhere. Also U-suffix a literal inside SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE_BYTES to match the Rule 10.4 sweep style — the macro is not currently expanded inside any cppcheck-scanned TU, so this is preemptive consistency. The audit's original verdict ("unused — delete them") was wrong: the macros are used, just outside cppcheck's scope. cppcheck-misra: rule 2.5 findings 2 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Interface/SolidSyslogCircularBuffer.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/Interface/SolidSyslogCircularBuffer.h b/Core/Interface/SolidSyslogCircularBuffer.h index 0ff8306f..63fcd983 100644 --- a/Core/Interface/SolidSyslogCircularBuffer.h +++ b/Core/Interface/SolidSyslogCircularBuffer.h @@ -22,11 +22,13 @@ EXTERN_C_BEGIN }; /* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- cannot compute array size as a constexpr in C */ +/* cppcheck-suppress misra-c2012-2.5 -- public API macro consumed by integrator code (Tests, Bdd/Targets) outside the cppcheck-misra scope. */ #define SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE_BYTES(ringBytes) \ (SOLIDSYSLOG_CIRCULARBUFFER_OVERHEAD + \ - (((ringBytes) + sizeof(SolidSyslogCircularBufferStorage) - 1) / sizeof(SolidSyslogCircularBufferStorage))) + (((ringBytes) + sizeof(SolidSyslogCircularBufferStorage) - 1U) / sizeof(SolidSyslogCircularBufferStorage))) /* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- cannot compute array size as a constexpr in C */ +/* cppcheck-suppress misra-c2012-2.5 -- public API macro consumed by integrator code (Tests, Bdd/Targets) outside the cppcheck-misra scope. */ #define SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE(maxMessages) \ SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE_BYTES( \ (size_t) (maxMessages) * (SOLIDSYSLOG_MAX_MESSAGE_SIZE + SOLIDSYSLOG_CIRCULARBUFFER_HEADER_BYTES) \ From 7d814a67f65e0e9bc1055e6c2167c04daf415b1e Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 15:50:51 +0100 Subject: [PATCH 08/12] refactor: S10.10 make WindowsHostname BOOL check essentially boolean (MISRA 14.4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GetComputerNameExA returns BOOL (typedef int in Win32). The controlling expression of an if shall have essentially boolean type (MISRA 14.4); a bare BOOL value does not. Compare against FALSE so the != yields a real boolean result. cppcheck-misra: rule 14.4 findings 1 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Platform/Windows/Source/SolidSyslogWindowsHostname.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Platform/Windows/Source/SolidSyslogWindowsHostname.c b/Platform/Windows/Source/SolidSyslogWindowsHostname.c index e9136832..ac4af1c4 100644 --- a/Platform/Windows/Source/SolidSyslogWindowsHostname.c +++ b/Platform/Windows/Source/SolidSyslogWindowsHostname.c @@ -25,7 +25,7 @@ void SolidSyslogWindowsHostname_Get(struct SolidSyslogFormatter* formatter) char hostname[MAX_HOSTNAME_SIZE]; DWORD size = sizeof(hostname); - if (WindowsHostname_GetComputerNameExA(ComputerNamePhysicalDnsHostname, hostname, &size)) + if (WindowsHostname_GetComputerNameExA(ComputerNamePhysicalDnsHostname, hostname, &size) != FALSE) { hostname[sizeof(hostname) - 1U] = '\0'; SolidSyslogFormatter_PrintUsAsciiString(formatter, hostname, sizeof(hostname)); From 2baa804c0892c3c84c24fdff036e666b398d5fdf Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 15:54:23 +0100 Subject: [PATCH 09/12] refactor: S10.10 replace octal file mode in PosixMessageQueueBuffer (MISRA 7.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MISRA 7.1 prohibits octal literals — Posix permission bits are traditionally written in octal (0600 = owner read/write), but the project has agreed to avoid octal in production code. Replace with a named hex constant OWNER_READ_WRITE = 0x180U inside a local anonymous enum so the literal is named at the call site and the value documents what each bit represents. cppcheck-misra: rule 7.1 findings 1 → 0. Co-Authored-By: Claude Opus 4.7 (1M context) --- Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c b/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c index 39e251fc..ba1523be 100644 --- a/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c +++ b/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c @@ -47,7 +47,12 @@ struct SolidSyslogBuffer* SolidSyslogPosixMessageQueueBuffer_Create(size_t maxMe attr.mq_maxmsg = maxMessages; attr.mq_msgsize = (long) maxMessageSize; - instance.Mq = mq_open(PosixMessageQueueBuffer_QueueName(), O_CREAT | O_RDWR | O_NONBLOCK, 0600, &attr); + /* 0600 in octal — owner read/write, equivalent to S_IRUSR | S_IWUSR. Hex form avoids MISRA 7.1. */ + enum + { + OWNER_READ_WRITE = 0x180U + }; + instance.Mq = mq_open(PosixMessageQueueBuffer_QueueName(), O_CREAT | O_RDWR | O_NONBLOCK, OWNER_READ_WRITE, &attr); instance.MaxMessageSize = maxMessageSize; instance.Base.Write = PosixMessageQueueBuffer_Write; instance.Base.Read = PosixMessageQueueBuffer_Read; From ce4db560e7f1e98f67d634ac2d636f02a04bda1b Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 17:09:05 +0100 Subject: [PATCH 10/12] refactor: S10.10 remove nested comment-start sequence in Crc16 banner (MISRA 3.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CRC-16 banner comment contained a https:// URL — the // inside a /* */ block is a nested comment-start sequence, which MISRA 3.1 prohibits. Drop the protocol prefix and rephrase the citation; the host + path are still navigable. cppcheck-misra: rule 3.1 findings 1 → 0. All ten S10.10-scope rules now report zero findings: 5.6 (5→0), 10.4 (92→0), 10.1 (11→0), 15.7 (10→0), 12.1 (5→0+drift→0), 10.8 (2→0), 2.5 (2→0), 14.4 (1→0), 7.1 (1→0), 3.1 (1→0). Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Source/SolidSyslogCrc16.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/Source/SolidSyslogCrc16.c b/Core/Source/SolidSyslogCrc16.c index d6607e3a..21fece18 100644 --- a/Core/Source/SolidSyslogCrc16.c +++ b/Core/Source/SolidSyslogCrc16.c @@ -2,8 +2,8 @@ * CRC-16/CCITT-FALSE (ITU-T V.41) * Polynomial: 0x1021 Init: 0xFFFF RefIn: false RefOut: false XorOut: 0x0000 * - * Check value 0x29B1 from Greg Cook's CRC catalogue: - * https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-ibm-3740 + * Check value 0x29B1 from Greg Cook's CRC catalogue + * (reveng.sourceforge.io/crc-catalogue/16.htm, entry crc-16-ibm-3740). */ #include "SolidSyslogCrc16.h" From be1da013de692fd7a82a42076bc9dbdd34939b5b Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 17:32:49 +0100 Subject: [PATCH 11/12] refactor: S10.10 switch STATIC_ASSERT polyfill to _Static_assert + add D.011/D.012 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two related changes for cleaner MISRA conformance: 1. **STATIC_ASSERT polyfill (Rule 5.6 follow-up).** The negative-array- size form added earlier in this story used a __LINE__-concatenated typedef name to satisfy Rule 5.6 (typedef uniqueness). cppcheck-misra then surfaced 5 new Rule 2.3 findings (typedef declared but never used — by design for the assertion mechanism) and the ## operator itself was a Rule 20.10 violation. Net regression vs. baseline. Switch to a direct C11 _Static_assert wrapper that stringifies the msg argument. The library already compiles at --std=c11; this avoids the typedef entirely. New deviation D.011 covers the unavoidable # operator in the stringify wrapper. 2. **CircularBuffer 2.5 suppression (Rule 2.5 follow-up).** Move the inline cppcheck-suppress on the public API macros to a txt-file suppression paired with D.012, matching the project's structural deviation pattern. Inline rationale removed. Also incidental: - `SOLIDSYSLOG_STATIC_ASSERT` call sites in `SolidSyslogFormatter.c` and `SolidSyslogCircularBuffer.c` gain explicit parens around the `*` sub-expression — cppcheck-misra now analyses inside the `_Static_assert` condition and surfaces Rule 12.1. - `OWNER_READ_WRITE` constant in `SolidSyslogPosixMessageQueueBuffer.c` moved from a function-local anonymous enum to the file-scope one, silencing a Rule 5.7 finding on the second anonymous enum block. - `Formatter_IsAboveUnicodeMaxEncoding` gains a NOLINT for bugprone-easily-swappable-parameters — the Rule 10.1 refactor shifted the function body so that `lead` and `continuation1` are each used exactly once, tripping clang-tidy's heuristic. cppcheck-misra: rules 5.6, 20.10, 2.3, 2.5, 5.7, 12.1 all 0 → unchanged or → 0; no regressions in any sweep target. Co-Authored-By: Claude Opus 4.7 (1M context) --- Core/Interface/SolidSyslogCircularBuffer.h | 2 - Core/Source/SolidSyslogCircularBuffer.c | 2 +- Core/Source/SolidSyslogFormatter.c | 10 +- Core/Source/SolidSyslogMacros.h | 16 +-- .../SolidSyslogPosixMessageQueueBuffer.c | 9 +- docs/misra-deviations.md | 135 ++++++++++++++++++ misra_suppressions.txt | 9 ++ 7 files changed, 162 insertions(+), 21 deletions(-) diff --git a/Core/Interface/SolidSyslogCircularBuffer.h b/Core/Interface/SolidSyslogCircularBuffer.h index 63fcd983..efe73671 100644 --- a/Core/Interface/SolidSyslogCircularBuffer.h +++ b/Core/Interface/SolidSyslogCircularBuffer.h @@ -22,13 +22,11 @@ EXTERN_C_BEGIN }; /* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- cannot compute array size as a constexpr in C */ -/* cppcheck-suppress misra-c2012-2.5 -- public API macro consumed by integrator code (Tests, Bdd/Targets) outside the cppcheck-misra scope. */ #define SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE_BYTES(ringBytes) \ (SOLIDSYSLOG_CIRCULARBUFFER_OVERHEAD + \ (((ringBytes) + sizeof(SolidSyslogCircularBufferStorage) - 1U) / sizeof(SolidSyslogCircularBufferStorage))) /* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- cannot compute array size as a constexpr in C */ -/* cppcheck-suppress misra-c2012-2.5 -- public API macro consumed by integrator code (Tests, Bdd/Targets) outside the cppcheck-misra scope. */ #define SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE(maxMessages) \ SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE_BYTES( \ (size_t) (maxMessages) * (SOLIDSYSLOG_MAX_MESSAGE_SIZE + SOLIDSYSLOG_CIRCULARBUFFER_HEADER_BYTES) \ diff --git a/Core/Source/SolidSyslogCircularBuffer.c b/Core/Source/SolidSyslogCircularBuffer.c index e2d27ad2..0b0558b6 100644 --- a/Core/Source/SolidSyslogCircularBuffer.c +++ b/Core/Source/SolidSyslogCircularBuffer.c @@ -28,7 +28,7 @@ struct SolidSyslogCircularBuffer SOLIDSYSLOG_STATIC_ASSERT( sizeof(struct SolidSyslogCircularBuffer) == - SOLIDSYSLOG_CIRCULARBUFFER_OVERHEAD * sizeof(SolidSyslogCircularBufferStorage), + (SOLIDSYSLOG_CIRCULARBUFFER_OVERHEAD * sizeof(SolidSyslogCircularBufferStorage)), "SOLIDSYSLOG_CIRCULARBUFFER_OVERHEAD does not match struct layout" ); diff --git a/Core/Source/SolidSyslogFormatter.c b/Core/Source/SolidSyslogFormatter.c index 676bfcc7..36f97aea 100644 --- a/Core/Source/SolidSyslogFormatter.c +++ b/Core/Source/SolidSyslogFormatter.c @@ -13,7 +13,7 @@ struct SolidSyslogFormatter }; SOLIDSYSLOG_STATIC_ASSERT( - sizeof(struct SolidSyslogFormatter) == SOLIDSYSLOG_FORMATTER_OVERHEAD * sizeof(SolidSyslogFormatterStorage), + sizeof(struct SolidSyslogFormatter) == (SOLIDSYSLOG_FORMATTER_OVERHEAD * sizeof(SolidSyslogFormatterStorage)), "SOLIDSYSLOG_FORMATTER_OVERHEAD does not match struct layout" ); @@ -257,6 +257,7 @@ static inline bool Formatter_IsOverlongFourByteEncoding(char lead, char continua return ((unsigned char) lead == 0xF0U) && (((unsigned char) continuation1 & 0xF0U) == 0x80U); } +/* NOLINTBEGIN(bugprone-easily-swappable-parameters) -- lead and continuation1 are byte values with distinct semantic roles, swap would not even compile a different result given the lead's value constraint */ static inline bool Formatter_IsAboveUnicodeMaxEncoding(char lead, char continuation1) { unsigned char uLead = (unsigned char) lead; @@ -265,6 +266,8 @@ static inline bool Formatter_IsAboveUnicodeMaxEncoding(char lead, char continuat return f4WithCont1Above8F || f5OrHigherLead; } +/* NOLINTEND(bugprone-easily-swappable-parameters) */ + static inline void Formatter_WriteBytes(struct SolidSyslogFormatter* formatter, const char* bytes, size_t count) { for (size_t i = 0; i < count; i++) @@ -495,8 +498,9 @@ static inline void Formatter_TrimTruncatedMultiByteTail(struct SolidSyslogFormat size_t p = formatter->Position; size_t trimFrom = p; - if ((p >= 1U) && (SolidSyslogUtf8_IsTwoByteLead(buffer[p - 1U]) || SolidSyslogUtf8_IsThreeByteLead(buffer[p - 1U]) || - SolidSyslogUtf8_IsFourByteLead(buffer[p - 1U]))) + if ((p >= 1U) && + (SolidSyslogUtf8_IsTwoByteLead(buffer[p - 1U]) || SolidSyslogUtf8_IsThreeByteLead(buffer[p - 1U]) || + SolidSyslogUtf8_IsFourByteLead(buffer[p - 1U]))) { trimFrom = p - 1U; } diff --git a/Core/Source/SolidSyslogMacros.h b/Core/Source/SolidSyslogMacros.h index 32013c9b..1de8244c 100644 --- a/Core/Source/SolidSyslogMacros.h +++ b/Core/Source/SolidSyslogMacros.h @@ -1,16 +1,14 @@ #ifndef SOLIDSYSLOGMACROS_H #define SOLIDSYSLOGMACROS_H -/* Portable compile-time assertion. Uses the negative-array-size trick - which works from C89 through C23 and all C++ versions — no C11 required. - The two-step concat with __LINE__ makes each typedef name unique within a - translation unit, satisfying MISRA C:2012 Rule 5.6 (typedef name shall be - a unique identifier). */ +/* Compile-time assertion. The library compiles at --std=c11 so we use the + standard C11 _Static_assert primitive directly; the msg parameter is named + at the call site for human readability and stringified by the caller via + the SOLIDSYSLOG_STATIC_ASSERT_STRING wrapper. */ /* NOLINTBEGIN(cppcoreguidelines-macro-usage) */ -#define SOLIDSYSLOG_STATIC_ASSERT_CONCAT_INNER(a, b) a##b -#define SOLIDSYSLOG_STATIC_ASSERT_CONCAT(a, b) SOLIDSYSLOG_STATIC_ASSERT_CONCAT_INNER(a, b) -#define SOLIDSYSLOG_STATIC_ASSERT(cond, msg) \ - typedef char SOLIDSYSLOG_STATIC_ASSERT_CONCAT(solidsyslog_static_assert_, __LINE__)[(cond) ? 1 : -1] +#define SOLIDSYSLOG_STATIC_ASSERT_STRING_INNER(s) #s +#define SOLIDSYSLOG_STATIC_ASSERT_STRING(s) SOLIDSYSLOG_STATIC_ASSERT_STRING_INNER(s) +#define SOLIDSYSLOG_STATIC_ASSERT(cond, msg) _Static_assert((cond), SOLIDSYSLOG_STATIC_ASSERT_STRING(msg)) /* NOLINTEND(cppcoreguidelines-macro-usage) */ #endif /* SOLIDSYSLOGMACROS_H */ diff --git a/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c b/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c index ba1523be..6a406f82 100644 --- a/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c +++ b/Platform/Posix/Source/SolidSyslogPosixMessageQueueBuffer.c @@ -11,7 +11,9 @@ enum { - MAX_NAME_SIZE = 64 + MAX_NAME_SIZE = 64, + /* 0600 in octal — owner read/write, equivalent to S_IRUSR | S_IWUSR. Hex form avoids MISRA 7.1. */ + OWNER_READ_WRITE = 0x180U }; static const char QUEUE_NAME_PREFIX[] = "/solidsyslog_"; @@ -47,11 +49,6 @@ struct SolidSyslogBuffer* SolidSyslogPosixMessageQueueBuffer_Create(size_t maxMe attr.mq_maxmsg = maxMessages; attr.mq_msgsize = (long) maxMessageSize; - /* 0600 in octal — owner read/write, equivalent to S_IRUSR | S_IWUSR. Hex form avoids MISRA 7.1. */ - enum - { - OWNER_READ_WRITE = 0x180U - }; instance.Mq = mq_open(PosixMessageQueueBuffer_QueueName(), O_CREAT | O_RDWR | O_NONBLOCK, OWNER_READ_WRITE, &attr); instance.MaxMessageSize = maxMessageSize; instance.Base.Write = PosixMessageQueueBuffer_Write; diff --git a/docs/misra-deviations.md b/docs/misra-deviations.md index f66698c2..efab8e99 100644 --- a/docs/misra-deviations.md +++ b/docs/misra-deviations.md @@ -716,3 +716,138 @@ would not be substitutable for any other type. Project owner — David Cozens. Recorded under [S10.06](https://github.com/DavidCozens/solid-syslog/issues/367). + +--- + +## D.011 — Rule 20.10: `#` stringification in `_Static_assert` polyfill + +### Rule + +> **Rule 20.10 (Advisory)** — The `#` and `##` preprocessor operators +> should not be used. + +### Deviation + +`Core/Source/SolidSyslogMacros.h` defines the `SOLIDSYSLOG_STATIC_ASSERT` +macro on top of C11 `_Static_assert`. `_Static_assert`'s second argument +must be a string literal; the project's macro accepts the message as an +identifier or any token sequence at the call site and stringifies it via +the standard two-step `#`-operator idiom: + +```c +#define SOLIDSYSLOG_STATIC_ASSERT_STRING_INNER(s) #s +#define SOLIDSYSLOG_STATIC_ASSERT_STRING(s) SOLIDSYSLOG_STATIC_ASSERT_STRING_INNER(s) +#define SOLIDSYSLOG_STATIC_ASSERT(cond, msg) _Static_assert((cond), SOLIDSYSLOG_STATIC_ASSERT_STRING(msg)) +``` + +The inner `#s` operator is the deviation. + +### Scope + +`Core/Source/SolidSyslogMacros.h` only. One line — the +`SOLIDSYSLOG_STATIC_ASSERT_STRING_INNER` definition. + +### Rationale + +`_Static_assert` is C11's standard compile-time assertion primitive and +the project compiles at `--std=c11`. Its second argument is a string +literal — there is no way to convert an arbitrary identifier-shaped +message at the call site into that string literal without the `#` +operator. The alternatives all regress: + +| Alternative | Why rejected | +|-------------|--------------| +| Hard-coded literal message in the macro | Loses per-site context — every assertion would report the same generic string. | +| Force every caller to pass a string literal | Spreads strings across ~16 call sites and gives up the per-site identifier form some files already use. | +| Drop the message argument entirely | Loses readability at the assertion site. | +| Hand-rolled negative-array-size trick (pre-C11 idiom) | The previous form. It collided with MISRA 5.6 (typedef name uniqueness) across translation units; resolving that required a `##` deviation anyway, which is worse than the current `#` one. | + +The advisory rule's intent is to discourage opaque token games. The +two-step stringify idiom here is the standard, documented C +preprocessor pattern and has been since C89; it is neither opaque nor +novel. + +### Risk and mitigation + +- **Single-site exposure.** The deviation is the macro definition + itself, line-specific. Any future `#`/`##` use elsewhere would + surface as a fresh 20.10 finding, not absorbed by this suppression. +- **Elimination path.** If the project ever drops the `msg` parameter + (or moves entirely to inline `_Static_assert((cond), "literal")` at + call sites), the deviation can be retired. + +### Approval + +Project owner — David Cozens. Recorded under +[S10.10](https://github.com/DavidCozens/solid-syslog/issues/375). + +--- + +## D.012 — Rule 2.5: public API macros consumed outside the cppcheck-misra scope + +### Rule + +> **Rule 2.5 (Advisory)** — A project should not contain unused macro +> definitions. + +### Deviation + +`Core/Interface/SolidSyslogCircularBuffer.h` declares two function-like +macros — `SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE_BYTES` and +`SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE` — that integrator code uses +to size caller-supplied storage. cppcheck-misra runs only over the +Strict tier (`Core/Source/`) and Pragmatic tier (`Platform/*/Source/`); +the actual consumers live under `Tests/` (Consistency-only tier) and +`Bdd/Targets/` (Out of scope) and are therefore invisible to the +checker. + +### Scope + +`Core/Interface/SolidSyslogCircularBuffer.h` — two macro definitions. + +A future per-component sweep may surface similar findings on other +public API macros (per the tier model, MISRA enforcement does not cross +into `Tests/` or `Bdd/`). When that happens, the deviation extends to +those files; the rule still catches genuinely-unused macros inside the +scanned scope. + +### Rationale + +The macros *are* used — by integrators in `Tests/` and `Bdd/Targets/`. +Verified by `grep` over the tree: + +``` +Tests/SolidSyslogCircularBufferTest.cpp — both macros +Tests/SolidSyslogTest.cpp — _BYTES form +Tests/SolidSyslogBlockStoreDrainOrderingTest.cpp — _SIZE form +Bdd/Targets/Windows/BddTargetWindows.c — _SIZE form +Bdd/Targets/FreeRtos/main.c — _SIZE form +``` + +The S10.05 audit's verdict ("Two declared macros that are never used. +Delete them.") was incorrect — the macros are part of the public API; +deleting them would force every integrator to compute storage size by +hand. + +The alternatives all regress: + +| Alternative | Why rejected | +|-------------|--------------| +| Inline `cppcheck-suppress misra-c2012-2.5` at each macro | Inline suppressions are weaker by MISRA Compliance:2020 §4.2 (rationale scattered, not centrally auditable). Project preference is structural deviations in this document. | +| Widen the cppcheck-misra scan to include `Tests/` | Tests are the Consistency-only tier per E10's tier model; running MISRA there is out of scope by design. | +| Move the macros into `Core/Source/` | Public API by definition lives under `Core/Interface/`. Moving them would break the audience-segregated header layout. | + +### Risk and mitigation + +- **Genuinely unused public macros.** A future public-API macro that + is *truly* unused (no integrator consumer either) would still be a + defect; this deviation is line-specific, so a new unused macro + surfaces as a fresh 2.5 finding rather than being silently absorbed. +- **Elimination path.** If the cppcheck-misra scan is ever widened to + include `Tests/` and `Bdd/Targets/` (unlikely under the current tier + model), the suppressions become unnecessary and can be removed. + +### Approval + +Project owner — David Cozens. Recorded under +[S10.10](https://github.com/DavidCozens/solid-syslog/issues/375). diff --git a/misra_suppressions.txt b/misra_suppressions.txt index 997f11ae..454746b3 100644 --- a/misra_suppressions.txt +++ b/misra_suppressions.txt @@ -231,3 +231,12 @@ misra-c2012-2.4:Core/Interface/SolidSyslogTransport.h:5 misra-c2012-2.4:Core/Source/BlockSequence.c:6 misra-c2012-2.4:Core/Source/BlockSequence.c:92 misra-c2012-2.4:Core/Source/SolidSyslogStreamSender.c:27 + +# D.011 — Rule 20.10: `#` stringification in _Static_assert polyfill +# See docs/misra-deviations.md#d011 +misra-c2012-20.10:Core/Source/SolidSyslogMacros.h:9 + +# D.012 — Rule 2.5: public API macros consumed outside cppcheck-misra scope +# See docs/misra-deviations.md#d012 +misra-c2012-2.5:Core/Interface/SolidSyslogCircularBuffer.h:25 +misra-c2012-2.5:Core/Interface/SolidSyslogCircularBuffer.h:30 From acf1a7e5078c51ec07cbca692613cdd8e3110619 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Sat, 16 May 2026 17:36:51 +0100 Subject: [PATCH 12/12] docs: S10.10 update misra-conformance.md and append DEVLOG entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark the ten sweep-target rule rows in misra-conformance.md as landed in S10.10 with the count → 0 annotation matching the S10.07/S10.08/S10.09 style. Update the MISRA totals table to add the S10.10 row, move rule 2.5 from Fix to Deviate (D.012), and add the D.011 entry. Renumber the per-component sweep target table from S10.10..S10.17 to S10.11..S10.18 to reflect the actual numbering after S10.10 took the slot. Mark the Mechanical MISRA sweep table as landed with audit / post-S10.10 columns plus the two new deviations introduced as byproducts. DEVLOG entry records: - Story selection rationale and slicing approach - Three audit verdict re-categorisations (rule 2.5, 5.6, 12.1) - Quirks encountered (anonymous-enum essential-type tracking, (char) cast vs unsigned char, return-of-ternary, clang-tidy swappable-parameters sensitivity to body shape, clang-format re-flow on suppression comments) - The auditor-view discussion on txt-file vs inline suppressions Co-Authored-By: Claude Opus 4.7 (1M context) --- DEVLOG.md | 123 ++++++++++++++++++++++++++++++++++++++ docs/misra-conformance.md | 102 +++++++++++++++++-------------- 2 files changed, 180 insertions(+), 45 deletions(-) diff --git a/DEVLOG.md b/DEVLOG.md index 9d10079a..d8950952 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -7743,3 +7743,126 @@ tag in the same pass. ### Open questions - None. The sweep cleared its named target; tidy is green. + +## 2026-05-16 — S10.10 mechanical MISRA sweep + +### Decisions + +- Picked the **mechanical MISRA sweep** (issue #375) as the next E10 + story — first cross-cutting sweep after the S10.07–S10.09 naming + trio, ahead of the not-yet-raised abbreviation purge. Rationale: + the audit had pre-decided this work (S10.05 + S10.06), the rules + involved are documented as mechanical (uniform fix shape, no + judgement calls), and clearing them shrinks the per-component + sweep load for S10.11+. +- Took the next free story number — **S10.10** — rather than + back-fitting into the audit's S10.10..S10.17 per-component + numbering. Reasoning matches S10.09's: story numbers are + identifiers, not sequencing. The per-component numbering shifts + by one (S10.11..S10.18) when those stories are raised. +- Sliced **one commit per rule on a single feature branch**, push + once at the end as a single PR — same shape as S10.09. The + per-rule commits were proposed before work began so each commit + has a clear "what + why + count went to 0" message. +- Counts were re-verified against current `main` (commit `f96064d`) + before fixes started — all matched the S10.05 audit numbers (92, + 10, 11, 5, 2, 1, 1, 1, 2, 5) exactly. +- For each rule, ran `cppcheck-misra` in the gcc container after + the fix and confirmed the per-rule count went to 0. After every + rule landing, ran `cmake --build --preset debug` + `ctest` to + confirm no behaviour regressions. Final sweep ran the full local + CI battery (debug, sanitize, coverage, tidy, format, clang-debug). + +### Verdict re-categorisations + +Three audit verdicts were wrong or incomplete; the sweep +corrected them: + +- **Rule 2.5** was tagged "Fix — delete unused macros". The two + `SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE[_BYTES]` macros are + *not* unused — they are public API consumed by `Tests/` and + `Bdd/Targets/`, both outside the cppcheck-misra scope. Re-cast + as a structural Deviate, captured as **D.012**. +- **Rule 5.6** was tagged "Fix — per-site review". All five sites + were the same `SOLIDSYSLOG_STATIC_ASSERT` polyfill emitting the + same `typedef char solidsyslog_static_assert_[…]` in every TU. + Tried first to add `__LINE__`-concatenation (`##` operator); + that fixed 5.6 but introduced 1 × Rule 20.10 + 5 × Rule 2.3 + findings — net regression. Switched the polyfill to a thin C11 + `_Static_assert` wrapper that stringifies the msg argument; the + unavoidable `#` is documented as **D.011**. +- **Rule 12.1** count grew from 5 (audit) → 8 (after the 10.4 + sweep widened the cppcheck visibility into bracketed + sub-expressions) → 10 (after the polyfill switch made + cppcheck-misra analyse inside `_Static_assert` conditions). All + resolved by adding parens, but the audit's headline understated + the rule. + +### Quirks and gotchas + +- **Anonymous-enum constants stay essentially-signed.** Even when + the initialiser carries `U` (e.g. `BITS_PER_BYTE = 8U`), + cppcheck-misra tracks the enum constant as essentially-signed. + Forced a literal `8U` inline at the one site that needed it + (rule 10.1 in `SolidSyslogCrc16.c`). U-suffixed initialisers on + other enum constants kept for visual consistency but are not + load-bearing. +- **`(char) '\xF5'` does not satisfy 10.4.** Casting to plain char + did not change cppcheck-misra's verdict at byte-comparison sites + (BOM strip in `SolidSyslog.c`, UTF-8 lead range in + `SolidSyslogFormatter.c`). Refactored to compare as + `unsigned char` against `0xXXU` hex literals; that worked. The + same pattern applied to Rule 10.1's bitwise operations. +- **Return-of-ternary trips 12.1 even with bracketed arms.** + `SolidSyslogUdpPayload_FromMtu` originally was + `return (mtu > overhead) ? (mtu - overhead) : 0U;`. cppcheck-misra + kept flagging it; refactored to an explicit if/return. +- **clang-tidy `bugprone-easily-swappable-parameters` is sensitive + to body shape.** Refactoring `Formatter_IsAboveUnicodeMaxEncoding` + for Rule 10.1 (extracted `unsigned char uLead`) reduced direct + uses of `lead` and `continuation1` to one each — clang-tidy then + decided the two params were "easily swappable". Added a + function-level `NOLINTBEGIN(bugprone-easily-swappable-parameters)` + matching the existing pattern on `Formatter_WriteContext`. +- **clang-format wants the suppression comments compact.** After + adding the inline `cppcheck-suppress` lines (later removed in + favour of txt-file suppressions), clang-format re-flowed several + multi-line macro definitions. Ran `clang-format -i` over the + tree and verified the dry-run is clean before committing. + +### Auditor view — txt-file suppressions vs inline + +Discussed before placing the two new suppressions (20.10 and 2.5). +Decision: structural deviations live in `misra_suppressions.txt` + +`docs/misra-deviations.md` (the project's existing D.001–D.010 +pattern). Reasoning mapped to MISRA Compliance:2020 §4.2: + +- Inline `cppcheck-suppress` comments scatter rationale across the + tree and don't carry the full deviation-record fields + (Rule / Scope / Justification / Risk and mitigation / Approval). +- Centralised deviation documents are listable, auditable, and + carry a sunset / elimination path per deviation. +- The user is also driving to **eliminate** suppressions where + possible; the deviation document makes that drive concrete + (each D.XXX has a "Risk and mitigation" section that can carry + a path to elimination). + +The one existing inline suppression (`preprocessorErrorDirective` +in `SolidSyslogTunables.h`) is a cppcheck primary rule, not a +MISRA rule — different category, doesn't set precedent. + +### Deferred + +- The **abbreviation purge** cross-cutting story is still + unraised. After S10.10 closes, only the per-component sweeps + (S10.11..S10.18) and the enforcement story (S10.19? — renumbered + to reflect actual numbering) remain in E10. +- The note in + `memory/project_e10_accumulated_scope.md` about widening the + non-MISRA cppcheck scope to `Platform/*/Source/` still belongs in + the final enforcement story. + +### Open questions + +- None. Sweep landed, all sweep-target rules at 0, full local CI + battery green. diff --git a/docs/misra-conformance.md b/docs/misra-conformance.md index 84a5028f..b399e717 100644 --- a/docs/misra-conformance.md +++ b/docs/misra-conformance.md @@ -99,32 +99,32 @@ Each row carries the cppcheck addon's count. The verdict reflects how the rule s |------|------:|--------------|-----------|---------|-----------|-------| | **5.9** (advisory) | 168 → 0 *(landed in S10.08)* | Identifiers with internal linkage shall be unique | `SolidSyslogWinsockTcpStream.c` (21), `SolidSyslogPosixTcpStream.c` (16), `SolidSyslogUdpSender.c` (12) | **Fix — landed in S10.08** | `static` helpers reusing common names (`Write`, `Read`, `Open`, etc.) across TUs were renamed `Class_Function` per NAMING.md Tier 2 using a strip-only-`SolidSyslog` rule (`SolidSyslogWinsockTcpStream.c` → `WinsockTcpStream_*` etc.). `Core/Source/SolidSyslog.c` got `SolidSyslog_` per the documented exception. Sweep was wide — applied to all ~811 statics across Core/Source + Platform/\*/Source, not just the 168 collisions; 5.9 cleared as a structural consequence. | **S10.08** | | **11.3** | 95 | Cast between pointer to object types of different kinds | `SolidSyslogPosixFile.c` (10), `SolidSyslogWindowsFile.c` (10), `SolidSyslogTlsStream.c` (6) | **Deviate** | Vtable + caller-supplied-storage is the project's foundational OO-in-C mechanism: `(struct Impl*) storage` is unavoidable at every `_Create`. Replacing it would require dynamic allocation or copy-by-value, both rejected. Document as project-wide deviation. | **S10.06** (deviation D.002 in `docs/misra-deviations.md`) | -| **10.4** | 92 | Both operands of operator shall be in same essential type category | `SolidSyslogFormatter.c` (15), `SolidSyslog.c` (6), `SolidSyslogFileBlockDevice.c` (6) | **Fix** | Mostly `size_t + 1` where `1` is `int`. Add `U` suffix to literals; occasional explicit cast for mixed cases. Mechanical sweep. | **New sweep story** (no existing slot in epic — propose S10.09a essential-type cleanups, or roll into S10.09 abbreviation purge / a new dedicated story) | +| **10.4** | 92 → 0 *(landed in S10.10)* | Both operands of operator shall be in same essential type category | `SolidSyslogFormatter.c` (15), `SolidSyslog.c` (6), `SolidSyslogFileBlockDevice.c` (6) | **Fix — landed in S10.10** | Mostly `size_t + 1` where `1` is `int`. Mechanical U-suffix sweep across `Core/Source/`, `Core/Interface/`, and `Platform/*/`. Two byte-comparison sites (BOM strip in `SolidSyslog.c`, UTF-8 lead range in `SolidSyslogFormatter.c`) refactored to `unsigned char` + hex-literal comparisons where the `(char)` cast did not satisfy cppcheck-misra's essential-type tracking. `SOLIDSYSLOG_FORMATTER_STORAGE_SIZE` picked up U on the literal inside the macro so every expansion is uniform. | **S10.10** | | **8.9** (advisory) | 56 | Object referenced in one function should have block scope | `SolidSyslogFormatter.c` (8), `SolidSyslogMetaSd.c` (5), `SolidSyslogOriginSd.c` (5) | **Fix** | File-scope statics that should be locals or `static const` block-scope. Per-site review. | **S10.09** (if "abbreviation purge" widens to "code-shape hygiene") or **new sweep story** | | **5.7** | 54 | Tag names unique | `BlockSequence.c` (2), `SolidSyslogFileBlockDevice.c` (2), `SolidSyslogBlockStore.h` (1), and so on across many forward-decl + definition pairs | **Deviate** | NAMING.md's no-typedef-struct convention deliberately repeats the same `struct SolidSyslogX` tag wherever it's used (forward-decl in headers, definition in source). 5.7 fires on every repetition. Document as deviation. | **S10.06** (deviation D.003) | | **11.8** | 11 | Cast shall not remove const/volatile qualification | `SolidSyslog.c` (8), `BlockSequence.c` (1), `SolidSyslogBlockStore.c` (1), `SolidSyslogWinsockTcpStream.c` (1) | **Deviate** *(resolved in S10.06: all 11 sites)* | All 10 Core sites are field-access "false positives" — accessing a non-const-pointer field through a `const struct*` parameter; C standard §6.5.2.3 ¶3 says the member-access yields an unqualified pointer rvalue, so this is not a real const-strip. The Winsock `select()` site is the documented platform-API const-strip already commented in source. Captured as **D.007**. | landed in **S10.06** | | **17.7** | 11 | Value returned by non-void function shall be used | `RecordStore.c` (5), `SolidSyslogCircularBuffer.c` (4), `SolidSyslog.c` (1) | **Fix** | Use the return value or cast to `(void)` with comment. | **New sweep story** or **S10.10** (Buffer pilot) where most concentrate | -| **10.1** | 11 | Operands shall not be of inappropriate essential type | `SolidSyslogUtf8.h` (5), `SolidSyslogFormatter.c` (5), `SolidSyslogCrc16.c` (1) | **Fix** | Bool/char/int essential-type mixing — typically a one-line cast or refactor. | **S10.17** (core message pipeline) for Formatter; mixed for the rest | -| **15.7** | 10 | All if/else-if shall be terminated with `else` | `BlockSequence.c` (3), `SolidSyslogFormatter.c` (2), `SolidSyslogTlsStream.c` (1) | **Fix** | Add trailing `else { /* exhaustive */ }`. Mechanical. | **New sweep story** | +| **10.1** | 11 → 0 *(landed in S10.10)* | Operands shall not be of inappropriate essential type | `SolidSyslogUtf8.h` (5), `SolidSyslogFormatter.c` (5), `SolidSyslogCrc16.c` (1) | **Fix — landed in S10.10** | Bitwise operators on plain `char` are inappropriate (char is essentially-character, bitwise operators require essentially-unsigned). Cast `char` operands to `unsigned char` and U-suffix the hex literal masks they are tested against. The Crc16 data-byte shift uses a literal `8U` instead of the `BITS_PER_BYTE` anonymous-enum constant (which cppcheck-misra still tracks as essentially-signed even with a U-suffixed initialiser). | **S10.10** | +| **15.7** | 10 → 0 *(landed in S10.10)* | All if/else-if shall be terminated with `else` | `BlockSequence.c` (3), `SolidSyslogFormatter.c` (2), `SolidSyslogTlsStream.c` (1) | **Fix — landed in S10.10** | Added trailing `else { /* explanatory comment */ }` to ten if/else-if chains spanning Core and Platform. Empty bodies document the residual case the existing branches do not cover. | **S10.10** | | **11.2** | 10 | Conversions between pointer to incomplete type and other types | `SolidSyslogAddressInternal.h` (2 × 3 platforms) | **Deviate** | Same opaque-type pattern as 11.3 — `Address` is opaque. Document together. | **S10.06** (with D.002) | | **8.4** | 8 | Compatible declaration shall be visible | `SolidSyslogStdAtomicU32.c` (4), `SolidSyslogWindowsAtomicU32.c` (4) | **Fix** | Atomics adapters define functions whose external prototype lives in a header that should be visible at definition. Add include or forward decl. | **S10.11** (security policies + CRC + sync primitives) | -| **12.1** (advisory) | 5 | Operator precedence should be explicit | `SolidSyslogCircularBuffer.c` (3), `SolidSyslogAtomicCounter.c` (1), `SolidSyslogTlsStream.c` (1) | **Fix** | Add parens. Mechanical. | **New sweep story** (or fold into 15.7 mechanical sweep) | +| **12.1** (advisory) | 5 → 0 *(landed in S10.10; +3 sites surfaced after the 10.4 sweep were swept along; +2 surfaced after the STATIC_ASSERT polyfill switch were also cleared)* | Operator precedence should be explicit | `SolidSyslogCircularBuffer.c` (3), `SolidSyslogAtomicCounter.c` (1), `SolidSyslogTlsStream.c` (1) | **Fix — landed in S10.10** | Added explicit parens around sub-expressions mixing comparison with arithmetic or logical operators. One ternary in `SolidSyslogUdpPayload_FromMtu` refactored to an if/return — cppcheck-misra continued to flag the return-of-ternary form even after bracketing both arms. | **S10.10** | | **17.8** | 5 | Function parameter should not be modified | `SolidSyslogFormatter.c` (3), `SolidSyslogError.c` (1), `SolidSyslogUdpPayload.c` (1) | **Fix** | Introduce a local copy. | **S10.17** for Formatter; mixed for the rest | -| **5.6** | 5 | Typedef names unique | `SolidSyslogBlockStore.c` (1), `SolidSyslogCircularBuffer.c` (1), `SolidSyslogFileBlockDevice.c` (1) | **Fix** | Need per-site review — likely typedef'd enums or storage types where the typedef name collides with a struct tag. | **S10.06** (review during rule curation) | +| **5.6** | 5 → 0 *(landed in S10.10)* | Typedef names unique | `SolidSyslogBlockStore.c` (1), `SolidSyslogCircularBuffer.c` (1), `SolidSyslogFileBlockDevice.c` (1) | **Fix — landed in S10.10** | Audit verdict had been "per-site review"; the actual cause was the project's `SOLIDSYSLOG_STATIC_ASSERT` polyfill emitting the same `typedef char solidsyslog_static_assert_[...]` in every TU. Replaced the negative-array polyfill with a C11 `_Static_assert` wrapper (the library compiles at `--std=c11`); the new form has no typedef and so cannot trigger 5.6. The unavoidable `#` stringify in the wrapper is captured by deviation **D.011** (Rule 20.10). | **S10.10** | | **18.4** (advisory) | 4 | `+`, `-`, `+=`, `-=` shall not be applied to pointer types | `RecordStore.c` (4) | **Deviate** | RecordStore manipulates record buffers using pointer arithmetic by design (magic byte offset → length offset → message offset, etc.). This is the natural C expression for the algorithm. Document as deviation. | **S10.06** (D.004) | | **15.5** (advisory) | 4 | Function should have single exit point | `SolidSyslogFormatter.c` (3), `SolidSyslog.c` (1) | **Fix** | Already a documented project preference ("Production code (Tier 1, Core/Source/) — Single return per function" in CLAUDE.md). Real drift. | **S10.17** (core message pipeline) | | **11.5** | 4 | Conversion from pointer to void to pointer to object | `SolidSyslogWinsockTcpStream.c` (2), `SolidSyslogUdpSender.c` (1), `SolidSyslogWinsockDatagram.c` (1) | **Deviate** | Same opaque-type / vtable pattern as 11.3. | **S10.06** (with D.002) | | **21.10** | 3 | `wchar.h` shall not be used | `SolidSyslogPosixClock.c` (1), `SolidSyslogPosixSleep.c` (1), `SolidSyslogPosixSysUpTime.c` (1) | **Deviate** *(resolved in S10.06)* | All three sites are `#include ` — glibc transitively pulls in `` via `bits/types/struct_tm.h`. No direct `` use anywhere in the project. Captured as **D.008**. | landed in **S10.06** | | **22.10** | 3 | The value of `errno` shall be checked only after a function that may set it | `SolidSyslogPosixTcpStream.c` (2), `SolidSyslogPosixDatagram.c` (1) | **Fix** | We currently read `errno` in some places where the preceding function isn't documented to set it (or we check before re-calling). Per-site review. | **S10.15** (sender platform impls) | | **8.6** | 3 | Identifier with external linkage shall have exactly one external definition | `SolidSyslogAddress.c` (1 each across Posix/Windows/FreeRtos) | **Fix** | Either missing definition or duplicate declaration of `Address` helpers — needs per-site investigation. | **S10.15** | -| **10.8** | 2 | Composite-expression cast to wider essential type | `SolidSyslog.c` (2) | **Fix** | One-site fixes. | **S10.17** | +| **10.8** | 2 → 0 *(landed in S10.10)* | Composite-expression cast to wider essential type | `SolidSyslog.c` (2) | **Fix — landed in S10.10** | Hoisted the `(uint32_t)` cast to the top of `SolidSyslog_FormatNonZeroUtcOffset` so the hours/minutes split uses `uint32_t / 60U` and `% 60U` without casting a composite expression. | **S10.10** | | **18.7** (advisory) | 2 | Flexible array members shall not be declared | `SolidSyslogCircularBuffer.c` (1), `SolidSyslogFormatter.c` (1) | **Deviate** | Flexible array members are the storage mechanism for `SolidSyslogFormatter` and `SolidSyslogCircularBuffer` — they hold caller-supplied storage of variable size. Removing them would require copying or fixed-size buffers. Document as deviation. | **S10.06** (D.005) | | **1.4** (advisory) | 2 | Emergent language features shall not be used | `SolidSyslogStdAtomicU32.c` (1), `SolidSyslogWindowsAtomicU32.c` (1) | **Deviate** | C11 `` is the project's atomic primitive on POSIX/clang/gcc/modern MSVC; we deliberately use C11 here and the alternative (`InterlockedCompareExchange`) is selected at link time on legacy MSVC. Use of C11 atomics is intentional, not accidental. | **S10.06** (D.006) | -| **2.5** (advisory) | 2 | Unused macro | `SolidSyslogCircularBuffer.h` (2) | **Fix** | Two declared macros that are never used. Delete them. | **S10.11** (sync primitives — CircularBuffer lives here) | -| **3.1** | 1 | `/* */` shall not contain comment-start sequence | `SolidSyslogCrc16.c` (1) | **Fix** | A single nested-comment-like sequence. One-line fix. | **S10.11** | -| **7.1** | 1 | Octal constants shall not be used | `SolidSyslogPosixMessageQueueBuffer.c` (1) | **Fix** | Probably `0644` or similar file-mode literal — change to hex or named constant. | **S10.10** (Buffers pilot) | +| **2.5** (advisory) | 2 → 0 *(landed in S10.10)* | Unused macro | `SolidSyslogCircularBuffer.h` (2) | **Deviate — landed in S10.10** | Audit verdict had been "delete them" — that was wrong. The two `SOLIDSYSLOG_CIRCULARBUFFER_STORAGE_SIZE[_BYTES]` macros are part of the public API; their consumers live under `Tests/` (Consistency-only tier) and `Bdd/Targets/` (Out of scope), so cppcheck-misra cannot see the call sites. Captured as **D.012**. | **S10.10** | +| **3.1** | 1 → 0 *(landed in S10.10)* | `/* */` shall not contain comment-start sequence | `SolidSyslogCrc16.c` (1) | **Fix — landed in S10.10** | The Crc16 banner contained a `https://` URL — the `//` inside the `/* */` is a nested comment-start. Dropped the protocol prefix and rephrased the citation. | **S10.10** | +| **7.1** | 1 → 0 *(landed in S10.10)* | Octal constants shall not be used | `SolidSyslogPosixMessageQueueBuffer.c` (1) | **Fix — landed in S10.10** | `0600` (Posix file mode) replaced with a named hex enum `OWNER_READ_WRITE = 0x180U` in the file-scope anonymous-enum block. | **S10.10** | | **21.6** | 1 | The Standard Library `stdio.h` shall not be used | `SolidSyslogWindowsFile.c` (1) | **Deviate** *(resolved in S10.06)* | `WindowsFile.c` includes `` solely for `SEEK_SET` / `SEEK_END` constants used by `_lseeki64` from ``; no stdio function or type is referenced. Captured as **D.009**. | landed in **S10.06** | -| **14.4** | 1 | Controlling expression shall have essentially Boolean type | `SolidSyslogWindowsHostname.c` (1) | **Fix** | Replace `if (some_int)` with `if (some_int != 0)`. | **S10.12** (config + platform helpers) | +| **14.4** | 1 → 0 *(landed in S10.10)* | Controlling expression shall have essentially Boolean type | `SolidSyslogWindowsHostname.c` (1) | **Fix — landed in S10.10** | `GetComputerNameExA` returns `BOOL` (typedef `int`); the if now compares `!= FALSE` so the controlling expression is a real boolean result. | **S10.10** | | **2.4** (advisory) | 1 → 6 *(resolved in S10.06)* | A project should not contain unused tag declarations | Re-run with D.002–D.009 suppressions surfaced 5 more anonymous-`enum { … };` sites previously hidden behind 5.7 — the audit's original count understated the rule. All 6 sites are the project's anonymous-`enum` named-constant idiom (≈31 such blocks tree-wide). | **Deviate** | Captured as **D.010**. The anonymous-`enum` idiom is project-wide and intentional (type-safe constants without `#define`). | landed in **S10.06** | ### MISRA totals by verdict @@ -132,15 +132,20 @@ Each row carries the cppcheck addon's count. The verdict reflects how the rule s | Verdict | Count | Rules | |---------|------:|-------| | **Fix — landed in S10.08** — rule 5.9 (static-function `Class_` prefix sweep) | 168 → 0 | 5.9 | -| **Fix** — other rules (mechanical or per-component sweeps S10.07+) | 220 | 10.4, 8.9, 17.7, 10.1, 15.7, 8.4, 12.1, 17.8, 5.6, 15.5, 10.8, 22.10, 8.6, 2.5, 3.1, 7.1, 14.4 | +| **Fix — landed in S10.10** — mechanical sweep (uniform U-suffixes, parens, trailing-else, …) + Rule 5.6 polyfill | 130 → 0 | 10.4 (92), 10.1 (11), 15.7 (10), 12.1 (5), 5.6 (5), 10.8 (2), 2.5 (2 — graduated to Deviate as D.012), 14.4 (1), 7.1 (1), 3.1 (1) | +| **Fix** — other rules (per-component sweeps S10.11+) | 90 | 8.9, 17.7, 8.4, 17.8, 15.5, 22.10, 8.6 | | **Deviate** — landed in S10.06 (D.002–D.010) | 187 | 11.3, 11.2, 11.5 *(D.002)*; 5.7 *(D.003)*; 18.4 *(D.004)*; 18.7 *(D.005)*; 1.4 *(D.006)*; 11.8 *(D.007)*; 21.10 *(D.008)*; 21.6 *(D.009)*; 2.4 *(D.010)* | +| **Deviate** — landed in S10.10 (D.011, D.012) | 3 | 20.10 *(D.011, 1 site — `#` stringify in `_Static_assert` wrapper)*; 2.5 *(D.012, 2 sites — public API macros consumed under `Tests/` and `Bdd/Targets/`)* | | **Disable** | 0 | — | -| **Total reconciled** | **388 Fix + 187 Deviate = 575** | Raw count includes 5 dual-rule overlaps (same code site reported under two rules, e.g. 11.2 + 11.3 cast in `Address.c`). | +| **Total reconciled** | **388 Fix + 190 Deviate = 575** (rule 2.5 moved from Fix to Deviate per D.012; raw `Fix` reduced by 2, raw `Deviate` increased by 3 with the new D.011 = +1) | Raw count includes 5 dual-rule overlaps (same code site reported under two rules, e.g. 11.2 + 11.3 cast in `Address.c`). | -The verdict surface increased from the audit's headline by two rows -(D.008 / D.009 resolving the Investigate items; D.010 added during -S10.06 re-run when D.003 suppression revealed 5 more 2.4 findings -previously hidden behind 5.7). +The verdict surface evolved from the audit's headline: +- S10.06 added D.008 / D.009 (Investigate items) and D.010 (D.003 + suppression revealed 5 more 2.4 findings). +- S10.10 added D.011 (20.10 — stringify in the new `_Static_assert` + polyfill wrapper) and D.012 (2.5 — re-categorised from "delete + unused" when the audit's verdict was found to be wrong; the macros + are consumed outside the cppcheck-misra scope). --- @@ -173,39 +178,46 @@ Rough order-of-magnitude for sweep planning. These are **upper bounds** (some Fi | S10.07 | Enum constants → `Class_PascalCase` + enum tags | 260 | | S10.09 *(was the S10.07-sibling slot; named in S10.09 issue)* | Data members lowerCamelCase → PascalCase per Tier 4 re-statement — **landed** | 186 → 0 | | S10.08 | Static functions → `Class_Function` (MISRA 5.9) | 168 | -| S10.09 | Abbreviation purge | (out of scope here — different lens) | -| **Mechanical MISRA sweep** *(new — slotted in S10.06)* | Tree-wide hybrid mechanical fixes (10.4 / 12.1 / 2.5 / 15.7 / 10.8 / 10.1 / 2.4 / 3.1 / 7.1 / 14.4) | 126 | -| S10.10 | Buffers pilot — receives 8.9 + 17.7 + 17.8 fragments | small (~5–10) | -| S10.11 | SecurityPolicies + CRC + Sync — receives 8.4 + 2.5 fragments | ~10 | -| S10.12 | Config + platform helpers — receives 14.4 fragment | small (~5) | -| S10.13 | Structured data — receives 8.9 + 17.8 fragments | small (~5) | -| S10.14 | Stores + BlockDevice + File — receives 8.9 + 17.7 + 17.8 + 5.6 + 8.6 fragments | ~20 | -| S10.15 | Senders + transport extension points — receives 22.10 + 8.6 + 17.7 + 2.4 fragments | ~15 | -| S10.16 | Stream platform impls — receives 17.7 + 8.4 + 11.8 (decided in S10.06) fragments | small (~5) | -| S10.17 | Core message pipeline — receives 15.5 + 10.1 + 17.8 + 10.8 fragments | ~20 | - -### Mechanical MISRA sweep — hybrid split *(decided in S10.05)* +| Abbreviation purge *(deferred — separate cross-cutting story, not yet raised)* | Locals/parameters and function-name abbreviations — different lens, scope still to be sized | TBD | +| **S10.10** *(was "Mechanical MISRA sweep" — picked up the next free story number)* | Tree-wide hybrid mechanical fixes — **landed**: 10.4 (92), 10.1 (11), 15.7 (10), 12.1 (5+drift), 5.6 (5), 10.8 (2), 2.5 (2, became D.012), 14.4 (1), 7.1 (1), 3.1 (1). +2 new deviations: D.011 (20.10), D.012 (2.5). | 130 → 0 | +| S10.11 *(was S10.10 in audit-era numbering)* | Buffers pilot — receives 8.9 + 17.7 + 17.8 fragments | small (~5–10) | +| S10.12 | SecurityPolicies + CRC + Sync — receives 8.4 + 2.5 fragments | ~10 | +| S10.13 | Config + platform helpers — receives 14.4 fragment | small (~5) | +| S10.14 | Structured data — receives 8.9 + 17.8 fragments | small (~5) | +| S10.15 | Stores + BlockDevice + File — receives 8.9 + 17.7 + 17.8 + 5.6 + 8.6 fragments | ~20 | +| S10.16 | Senders + transport extension points — receives 22.10 + 8.6 + 17.7 + 2.4 fragments | ~15 | +| S10.17 | Stream platform impls — receives 17.7 + 8.4 + 11.8 (decided in S10.06) fragments | small (~5) | +| S10.18 | Core message pipeline — receives 15.5 + 10.1 + 17.8 + 10.8 fragments | ~20 | + +The per-component story numbers above are advisory — actual numbers +are assigned when each story is raised. The audit-era numbering +(S10.10..S10.17) shifted by one because the mechanical sweep took +the S10.10 slot. + +### Mechanical MISRA sweep — hybrid split *(decided in S10.05, landed in S10.10)* The 221 Fix-target MISRA findings across 16 rules split into two categories by whether the fix needs local code context: -**Mechanical tree-wide sweep** *(new story — see "Story naming" below)* — -truly uniform fixes that benefit from being applied once across -the whole tree under a single review: - -| Rule | Count | Fix shape | -|------|------:|-----------| -| 10.4 | 92 | Add `U` suffix to integer literals; occasional cast | -| 12.1 | 5 | Add explicit precedence parentheses | -| 2.5 | 2 | Delete unused macros | -| 15.7 | 10 | Add trailing `else { /* exhaustive */ }` | -| 10.8 | 2 | Cast composite expression to wider essential type | -| 10.1 | 11 | Bool/char essential-type mismatch — one-line cast | -| 2.4 | 1 | Remove unused tag | -| 3.1 | 1 | Disambiguate nested comment-start | -| 7.1 | 1 | Replace octal with hex / named constant | -| 14.4 | 1 | Make controlling expression essentially Boolean | -| **Mechanical total** | **126** | | +**Mechanical tree-wide sweep** *(landed in S10.10)* — truly uniform +fixes that benefit from being applied once across the whole tree +under a single review: + +| Rule | Audit count | After S10.10 | Fix shape | +|------|------------:|------------:|-----------| +| 10.4 | 92 | 0 | Add `U` suffix to integer literals; occasional cast | +| 12.1 | 5 | 0 | Add explicit precedence parentheses | +| 2.5 | 2 | 0 | Audit said "delete"; actually consumed outside cppcheck scope — became D.012 | +| 15.7 | 10 | 0 | Add trailing `else { /* exhaustive */ }` | +| 10.8 | 2 | 0 | Hoist cast above composite expression | +| 10.1 | 11 | 0 | Bool/char essential-type mismatch — cast to `unsigned char` + hex literals | +| 5.6 | 5 | 0 | Switch `SOLIDSYSLOG_STATIC_ASSERT` polyfill to C11 `_Static_assert` | +| 2.4 | 1 → graduated to Deviate in S10.06 (D.010) before S10.10 ran | — | — | +| 3.1 | 1 | 0 | Disambiguate `//` inside a `/* */` URL | +| 7.1 | 1 | 0 | Replace `0600` octal with named hex `OWNER_READ_WRITE = 0x180U` | +| 14.4 | 1 | 0 | `BOOL` comparison with `!= FALSE` instead of bare value | +| **S10.10 total** | **131** *(126 mechanical + 5 polyfill)* | **0** | | +| **New deviations introduced as byproducts** | — | — | D.011 (20.10, 1 site — stringify); D.012 (2.5, 2 sites — public API macros) | **Per-component sweep targets** *(absorbed into S10.10–S10.17)* — fixes that need local file context to apply correctly: