Skip to content

Commit aa638d2

Browse files
DavidCozensclaude
andauthored
fix: report a missing MetaSd counter as CRITICAL, like every other Create (#751)
* fix: report a missing MetaSd counter as CRITICAL, like every other Create SolidSyslogMetaSd_Create reported WARNING for a NULL config or counter while returning the Null structured data, so the meta element is never emitted. Its sibling SolidSyslogTimeQualitySd_Create reports CRITICAL for the same shape of fault, as do the 24 other sites that reach BAD_CONFIG_FATAL_SEVERITY, and docs/error-severity.md states the test: CRITICAL is where <Class>_Create returned the shared Null sibling. An audit of all 154 report sites in Core and Platform found MetaSd to be the only place a BAD_CONFIG fault leaving the component unbuilt was reported as WARNING. The other four WARNING sites in that category are built-and-delivering by design — a block grown to the minimum usable size, and a TLS stream with no expected identity — and stay as they are. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * docs: S23.22 keep Null objects out of the RFC compliance tables Two rows hung caveats off Null-object behaviour — a rejected counter leaving the meta element unemitted, and an exhausted pool returning 1 for every record. Both read as limits on what the library supports. They are neither: a Null object appears only where a component could not be built, which is a wiring fault reported through the error handler and fixed before shipping. The preamble now says that once, and links docs/error-severity.md for the severity. The rows keep what belongs to the requirement — which parameters a NULL config field omits, and that the counter is required because without one there is no sequenceId to carry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent df4464d commit aa638d2

3 files changed

Lines changed: 23 additions & 8 deletions

File tree

Core/Source/SolidSyslogMetaSdStatic.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,19 @@ static bool MetaSd_IsValidConfig(const struct SolidSyslogMetaSdConfig* config)
5151
bool valid = false;
5252
if (config == NULL)
5353
{
54-
MetaSd_Report(SOLIDSYSLOG_SEVERITY_WARNING, SOLIDSYSLOG_CAT_BAD_CONFIG, SOLIDSYSLOG_META_SD_ERROR_NULL_CONFIG);
54+
MetaSd_Report(
55+
SOLIDSYSLOG_BAD_CONFIG_FATAL_SEVERITY,
56+
SOLIDSYSLOG_CAT_BAD_CONFIG,
57+
SOLIDSYSLOG_META_SD_ERROR_NULL_CONFIG
58+
);
5559
}
5660
else if (config->Counter == NULL)
5761
{
58-
MetaSd_Report(SOLIDSYSLOG_SEVERITY_WARNING, SOLIDSYSLOG_CAT_BAD_CONFIG, SOLIDSYSLOG_META_SD_ERROR_NULL_COUNTER);
62+
MetaSd_Report(
63+
SOLIDSYSLOG_BAD_CONFIG_FATAL_SEVERITY,
64+
SOLIDSYSLOG_CAT_BAD_CONFIG,
65+
SOLIDSYSLOG_META_SD_ERROR_NULL_COUNTER
66+
);
5967
}
6068
else
6169
{

Tests/SolidSyslogMetaSdTest.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,24 +287,24 @@ TEST(SolidSyslogMetaSd, FormatEmitsNothingWhenCreatedWithNullConfig)
287287
STRCMP_EQUAL("", SolidSyslogFormatter_AsFormattedBuffer(formatter));
288288
}
289289

290-
TEST(SolidSyslogMetaSd, CreateWithNullConfigReportsWarning)
290+
TEST(SolidSyslogMetaSd, CreateWithNullConfigReportsCritical)
291291
{
292292
recreateWith(nullptr);
293293

294294
CALLED_FAKE(ErrorHandlerFake_Handle, ONCE);
295-
LONGS_EQUAL(SOLIDSYSLOG_SEVERITY_WARNING, ErrorHandlerFake_LastSeverity());
295+
LONGS_EQUAL(SOLIDSYSLOG_SEVERITY_CRITICAL, ErrorHandlerFake_LastSeverity());
296296
POINTERS_EQUAL(&MetaSdErrorSource, ErrorHandlerFake_LastSource());
297297
UNSIGNED_LONGS_EQUAL(SOLIDSYSLOG_CAT_BAD_CONFIG, ErrorHandlerFake_LastCategory());
298298
UNSIGNED_LONGS_EQUAL(SOLIDSYSLOG_META_SD_ERROR_NULL_CONFIG, ErrorHandlerFake_LastDetail());
299299
}
300300

301-
TEST(SolidSyslogMetaSd, CreateWithNullCounterReportsWarning)
301+
TEST(SolidSyslogMetaSd, CreateWithNullCounterReportsCritical)
302302
{
303303
config.Counter = nullptr;
304304
recreate();
305305

306306
CALLED_FAKE(ErrorHandlerFake_Handle, ONCE);
307-
LONGS_EQUAL(SOLIDSYSLOG_SEVERITY_WARNING, ErrorHandlerFake_LastSeverity());
307+
LONGS_EQUAL(SOLIDSYSLOG_SEVERITY_CRITICAL, ErrorHandlerFake_LastSeverity());
308308
POINTERS_EQUAL(&MetaSdErrorSource, ErrorHandlerFake_LastSource());
309309
UNSIGNED_LONGS_EQUAL(SOLIDSYSLOG_CAT_BAD_CONFIG, ErrorHandlerFake_LastCategory());
310310
UNSIGNED_LONGS_EQUAL(SOLIDSYSLOG_META_SD_ERROR_NULL_COUNTER, ErrorHandlerFake_LastDetail());

docs/rfc-compliance.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ Where a shipped platform does not meet an obligation, its own page records the
1919
exception and links the issue tracking it, and the
2020
[capability matrix](platforms/index.md) shows which platform fills which role.
2121

22+
Every status below describes a correctly wired instance. A component that could
23+
not be built — a dependency left NULL, a pool sized too small — is replaced by its
24+
Null object and reported through the error handler, at the severity
25+
[docs/error-severity.md](error-severity.md) sets for a `Create` that fell back.
26+
That is a wiring fault to fix before shipping, not a limit on what the library
27+
supports, so the rows do not restate it.
28+
2229
## RFC 5424 — The Syslog Protocol
2330

2431
Checked against [RFC 5424](https://www.rfc-editor.org/rfc/rfc5424.html), Standards Track.
@@ -59,8 +66,8 @@ Checked against [RFC 5424](https://www.rfc-editor.org/rfc/rfc5424.html), Standar
5966
| [7.2.3](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.2.3) | software — MUST NOT be longer than 48 characters | Supported | Enforced. `SolidSyslogOriginSd` writes the value through `SolidSyslogSdValue_BoundedString` with a 48 bound, so an over-long string is truncated rather than emitted. The bound counts decoded bytes — what a receiver's un-escaping decoder extracts — so for multi-byte UTF-8 it truncates earlier than the 48 characters §7.2.3 allows, never later |
6067
| [7.2.4](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.2.4) | swVersion — MUST NOT be longer than 32 characters | Supported | Enforced at 32 on the same terms as `software` above |
6168
| [7.2.5](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.2.5) | origin example | N/A | Illustrative. States no requirement of its own |
62-
| [7.3](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.3) | meta SD — sequenceId, sysUpTime, language | Supported | `SolidSyslogMetaSd` covers all three IANA-registered parameters. `sequenceId` (§7.3.1) sourced via an injected `SolidSyslogAtomicCounter`. `sysUpTime` (§7.3.2 / RFC 3418 `TimeTicks`) sourced via a `SolidSyslogSysUpTimeFunction` callback returning `uint32_t` hundredths, the type giving RFC 3418's natural wrap; the [capability matrix](platforms/index.md) shows which platforms supply one. `language` (§7.3.3 / BCP 47) sourced via a `SolidSyslogSdValueFunction` callback streaming into a `SolidSyslogSdValue`, which applies SD-PARAM-VALUE escaping per §6.3.3. `sysUpTime` and `language` are independently optional — a NULL field in `SolidSyslogMetaSdConfig` omits that parameter. The counter is not: `SolidSyslogMetaSd_Create` rejects a NULL `Counter` with a `WARNING` and returns the Null structured data, so the element is not emitted at all |
63-
| [7.3.1](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.3.1) | meta SD — sequenceId wraps at 2147483647 to 1 | Supported | The [AtomicCounter](api/structSolidSyslogAtomicCounter.md) contract carries the wrap: values run [1, `SOLIDSYSLOG_SEQUENCE_ID_MAX`] and never 0. The id is taken when a message is raised, so it records the order messages originated in. Delivery order may differ — messages raised from several threads, or any transport that reorders — and a SIEM recovers origination order by sorting on sequenceId, which is what it is for. An exhausted counter pool yields the Null counter, which returns 1 for every record, so gap detection stops being meaningful while logging continues |
69+
| [7.3](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.3) | meta SD — sequenceId, sysUpTime, language | Supported | `SolidSyslogMetaSd` covers all three IANA-registered parameters. `sequenceId` (§7.3.1) sourced via an injected `SolidSyslogAtomicCounter`. `sysUpTime` (§7.3.2 / RFC 3418 `TimeTicks`) sourced via a `SolidSyslogSysUpTimeFunction` callback returning `uint32_t` hundredths, the type giving RFC 3418's natural wrap; the [capability matrix](platforms/index.md) shows which platforms supply one. `language` (§7.3.3 / BCP 47) sourced via a `SolidSyslogSdValueFunction` callback streaming into a `SolidSyslogSdValue`, which applies SD-PARAM-VALUE escaping per §6.3.3. `sysUpTime` and `language` are independently optional — a NULL field in `SolidSyslogMetaSdConfig` omits that parameter. The counter is required: without one there is no sequenceId, so there is no meta element to emit |
70+
| [7.3.1](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.3.1) | meta SD — sequenceId wraps at 2147483647 to 1 | Supported | The [AtomicCounter](api/structSolidSyslogAtomicCounter.md) contract carries the wrap: values run [1, `SOLIDSYSLOG_SEQUENCE_ID_MAX`] and never 0. The id is taken when a message is raised, so it records the order messages originated in. Delivery order may differ — messages raised from several threads, or any transport that reorders — and a SIEM recovers origination order by sorting on sequenceId, which is what it is for. |
6471
| [7.3.2](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.3.2) | sysUpTime — MUST be a decimal integer, digits only | Supported | The callback returns `uint32_t` hundredths and the value is written through `SolidSyslogSdValue_Uint32`, which emits decimal digits only. §7.3.2 also notes the SNMP management portion may differ from the syslog one, which is the integrator's to reconcile |
6572
| [7.3.3](https://www.rfc-editor.org/rfc/rfc5424.html#section-7.3.3) | language — MUST be a BCP 47 language identifier | Supported | Streamed through a `SolidSyslogSdValueFunction` into a `SolidSyslogSdValue`, which applies §6.3.3 escaping. The parameter is optional and the identifier is the integrator's to supply; the library does not parse BCP 47 |
6673
| [8.1](https://www.rfc-editor.org/rfc/rfc5424.html#section-8.1) | UNICODE — shortest-form encoding REQUIRED | Supported | RFC 3629 validation at the formatter primitives rejects overlong encodings, substituting each ill-formed byte with U+FFFD per Unicode §3.9, so a non-shortest-form sequence cannot pass through |

0 commit comments

Comments
 (0)