CNA-BUG-210: A diagnostics name or resource label longer than 4,096 bytes makes every Inspector snapshot or event batch that contains it fail with LimitExceeded

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; executed for this entry (the Evidence section names exactly what was run); tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

Diagnostics accepts names up to 1 MiB and labels of any length, but the Inspector protocol caps strings at 4,096 bytes and refuses the whole response, so one long name breaks the affected Inspector views for the rest of the process.

Identifier
CNA-BUG-210
Category
Bug
Subsystem
Diagnostics & Inspector
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (a triage suggestion, not a project priority)
Evidence basis
Reproduced: executed for this entry (the Evidence section names exactly what was run)
Tests touching this area
Yes: see Current tests
Affected contract
CNA::Inspector protocol v1 SnapshotResponse and EventsResponse encoding (ProtocolCodec::Encode) over diagnostics provider v1 data

Expected behaviour

The Inspector is a consumer of the unchanged provider v1 contract, and inspector.md says oversized complete snapshots are refused rather than partially mislabeled. That refusal policy is therefore intended, but it should be predictable: either the two modules agree on one string bound that registration enforces and the documentation states, or the refusal is limited to the offending item instead of every snapshot and event batch that contains it.

Actual behaviour at TARGET

RegisterMetric and RegisterName accept names up to MaximumTraceNameBytes (1 MiB); CopyResource copies labels and formats without a bound. Protocol.cpp's Writer::String throws std::length_error above MaximumStringBytes (4,096) for metric names (WriteMetric, including per-frame metrics), resource label and format (WriteResource) and resolved event names, and Agent::Impl::HandleRequest turns that into ErrorCode::LimitExceeded for the whole request. Metrics are never unregistered, so the overview request (metrics and frames) fails for the rest of the process; the Resources view fails while such a resource lives, and each event batch containing such a name fails. docs/inspector.md says oversized complete snapshots are refused rather than partially mislabeled, but neither states the 4,096-byte bound nor offers a remedy for a long name (its troubleshooting line says only “reduce event count or preview bounds”). Engine labels are short literals ("Texture2D"), so the trigger is application instrumentation.

Source locations

Evidence

Read at 009d40f5. Executed: TARGET's Diagnostics.cpp and Protocol.cpp compiled unchanged with g++ 14.2 -std=c++23 -DCNA_DIAGNOSTICS_LEVEL=2 (both need only the standard library) and driven directly: a 5,000-byte counter name registered (non-zero id) and ProtocolCodec::Encode of a metrics snapshot threw length_error; a 5,000-byte resource label registered and the resources snapshot threw likewise. The agent round trip and the browser view were not run; the mapping to LimitExceeded is by reading.

Independent re-verification: Reproduced by the audit at 009d40f5. TARGET's Diagnostics.cpp and Protocol.cpp were compiled unchanged (g++ -std=c++23 -DCNA_DIAGNOSTICS_LEVEL=2) and driven directly: a 4,096-byte counter name encoded, while 4,097-byte and 5,000-byte counter names, a 5,000-byte resource label and a 5,000-byte resolved event name were all registered (non-zero id) and made ProtocolCodec::Encode throw length_error; registration accepts exactly 1 MiB and refuses 1 MiB plus one byte. The agent round trip and the browser view were not run; the mapping to LimitExceeded is by reading Agent.cpp. inspector.md documents the refusal of oversized complete snapshots but neither the 4,096-byte string bound nor its remedy.

Focused reproduction

Compiled and run as described under Evidence.

using namespace CNA::Diagnostics;
(void)SetRuntimeMode(Mode::Stats);
CounterHandle counter(std::string(5000, 'n'));   // accepted: id != 0
CNA::Inspector::SnapshotResponse response;
response.includedParts = static_cast<std::uint32_t>(CNA::Inspector::SnapshotPart::Metrics);
response.snapshot = GetProvider().CaptureSnapshot();
(void)CNA::Inspector::ProtocolCodec::Encode(response, 1);
// throws std::length_error: "Inspector string exceeds its protocol bound"

Current tests

InvalidIdentityStringsFailBeforeProviderAccess covers the agent's own identity strings (a 4,097-byte application name is refused at Start); protocol tests cover oversized input on decode. No test feeds a provider-valid long name or label.

Regression test

An InspectorAgentTests case whose fake provider returns a 5,000-byte metric name and resource label, asserting the documented handling (truncation or per-item omission) instead of a whole-response LimitExceeded; or a diagnostics test that registration refuses names above the Inspector's bound.

Blast radius

Applications whose own instrumentation registers long (for example generated) names or labels, and their Inspector sessions; the diagnostics core and in-process consumers are unaffected.

Workaround

Keep diagnostic names and labels under 4,096 bytes.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index