Repository navigation
5.1 Validation Framework and ProtocolLimits
Relevant source files
The following files were used as context for generating this wiki page:
This page details the validation framework implemented in src/validation/mod.rs, src/validation/bounded.rs, and src/validation/checks.rs. The validation layer enforces a fail-closed ingress contract for all public wire payloads, protecting memory and compute resources from malformed or malicious payloads without relying on untrusted serializer size hints.
Sources: src/validation/mod.rs:3-27(), src/validation/bounded.rs:1-12(), src/validation/checks.rs:1-9()
The validation framework revolves around the Validate trait defined in src/validation/mod.rs:89-97(). It exposes two methods:
-
validate(&self) -> Result<(), ValidationError>: Evaluates the payload against [ProtocolLimits::DEFAULT]. -
validate_with(&self, limits: ProtocolLimits) -> Result<(), ValidationError>: Evaluates the payload against custom resource boundaries.
graph TD
IncomingPayload["Incoming Wire Payload"] --> Deserialization["Deserialization & bounded parsing"]
Deserialization --> ValidateCall["Validate::validate() or validate_with()"]
ValidateCall --> CheckLimits["ProtocolLimits Checks"]
ValidateCall --> CheckValues["Finite & Range Checks"]
CheckLimits --> ResultOK["Result::Ok(())"]
CheckValues --> ResultOK
CheckLimits --> ResultErr["Result::Err(ValidationError)"]
CheckValues --> ResultErr
classDef default fill:#fff,stroke:#000,stroke-width:1px;
Figure 1: Validation Execution Flow across Code Entities.
Sources: src/validation/mod.rs:88-97()
Resource bounds are governed by the ProtocolLimits struct (src/validation/mod.rs:47-64()). It defines explicit maximum thresholds for collections, strings, and aggregated records to prevent denial-of-service vectors via memory exhaustion.
| Field Name | Type | Default Value | Description |
|---|---|---|---|
max_channel_values |
usize |
65_536 |
Max length of stimulus values, embeddings, masks, gradient vectors, traces, and float arrays. |
max_spike_events |
usize |
65_536 |
Max length of SpikeBatch.spikes. |
max_traces |
usize |
65_536 |
Max length of TraceBatch.traces. |
max_gradients |
usize |
65_536 |
Max length of GradientBatch.gradients. |
max_metadata_entries |
usize |
256 |
Max keys in BatchMetadata.custom and ConfigPayload.config. |
max_string_bytes |
usize |
1_024 |
Max UTF-8 bytes for strings (session IDs, keys, values, source, layer ID). |
max_aggregate_records |
usize |
131_072 |
Max nested records aggregated inside one payload. |
The associated constant ProtocolLimits::DEFAULT provides the standard pre-configured limits used by deserialization hooks (src/validation/mod.rs:71-80()).
Sources: src/validation/mod.rs:47-80()
To prevent untrusted input from exploiting serde collection capacity hints, src/validation/bounded.rs implements explicit custom visitors. These reject sequences and maps immediately upon exceeding limits without trusting size_hint (src/validation/mod.rs:13-16()).
-
bounded_vec: Deserializes sequences up to a specifiedmaxitem count, usingreject_seq_overflowif limits are exceeded (src/validation/bounded.rs:82-126()). -
bounded_opt_vec: Handles optional sequences with equivalent bounds enforcement (src/validation/bounded.rs:128-171()). -
bounded_string: Deserializes strings, enforcingmaxUTF-8 byte length viaStringVisitor(src/validation/bounded.rs:173-222()). -
bounded_opt_string: Optional variant for bounded strings (src/validation/bounded.rs:224-240()).
graph TD
DeserializerInput["Serde Deserializer Stream"] --> BoundedVec["bounded_vec() Visitor"]
BoundedVec --> CheckSize{"Current Len >= Max?"}
CheckSize -- Yes --> RejectOverflow["reject_seq_overflow() -> ValidationError::LimitExceeded"]
CheckSize -- No --> PushItem["Push Element into Vec"]
PushItem --> CheckMore{"More Elements?"}
CheckMore -- Yes --> CheckSize
CheckMore -- No --> ReturnVec["Return Vec<T>"]
classDef default fill:#fff,stroke:#000,stroke-width:1px;
Figure 2: Sequence Deserialization Data Flow in bounded_vec.
Sources: src/validation/bounded.rs:13-126(), src/validation/mod.rs:11-16()
src/validation/checks.rs provides primitive validation helper functions used during struct-level Validate::validate implementation calls:
-
check_string/check_opt_string: Validates that string length does not exceedlimits.max_string_bytes(src/validation/checks.rs:10-34()). -
check_count: Asserts that an actual count does not exceed a specified limit (src/validation/checks.rs:36-42()). -
check_finite: Verifies that anf32value is finite (value.is_finite()), raising aValidationError::non_finiteotherwise (src/validation/checks.rs:44-50()). -
check_finite_slice: Iterates through anf32slice, verifying each element's finiteness with indexed path formatting (src/validation/checks.rs:52-62()). -
check_range: Combines finite checking with lower/upper bound assertions (src/validation/checks.rs:64-76()). -
add_to_total: Safely accumulates aggregate record counts using checked arithmetic, rejecting overflows againstmax_aggregate_records(src/validation/checks.rs:78-96()). -
check_unique_strings: Ensures uniqueness of key identifiers within collections (src/validation/checks.rs:121-137()).
Sources: src/validation/checks.rs:10-137()
The validation framework guarantees fail-closed semantics through strict deserialization boundaries:
-
Size Hint Rejection: Serde deserializers ignore capacity hints provided by the wire payload if they exceed
ProtocolLimits::DEFAULT(src/validation/mod.rs:13-16()). -
Overflow Detection: Sequences that exceed the maximum bound trigger an immediate parse error via
IgnoredAnyscan parsing (src/validation/bounded.rs:13-27()). -
Finite Checks: Non-finite floating-point values (
NaN,+inf,-inf) are rejected across all tensor streams and readout configurations (src/validation/checks.rs:44-62()).
Sources: src/validation/mod.rs:11-26(), src/validation/bounded.rs:13-27(), src/validation/checks.rs:44-62()
- Home
- 1. Overview
- 1.1. Getting Started
- 1.2. Architecture Overview
- 1.3. Crate Exports and Module Map
- 2. Core Abstractions
- 2.1. IpcBackend Trait
- 2.2. HybridFlowBackend Trait
- 2.3. BackendFactory and BackendType
- 2.4. Error Handling
- 3. Backend Implementations
- 3.1. RustBackend
- 3.2. ZmqIpcBackend
- 3.3. ZMQ Readout Parsing and Golden Frames
- 3.4. Structured ZeroMQ IpcMessage Transport
- 4. IPC Protocol and Data Models
- 4.1. IpcMessage Protocol
- 4.2. Batch Data Types
- 4.3. NeuromodulatorSnapshot and Neuromodulator Packet
- 4.4. StimulusBatch and Runtime Ingress
- 4.5. Deserialization Hooks and Model Compat Aliases
- 5. Validation and Wire Compatibility
- 5.1. Validation Framework and ProtocolLimits
- 5.2. ValidationError and ValidationKind
- 5.3. WireCompatibility and Envelope Decoding
- 5.4. Canonical Wire-v1 Encoding
- 6. corpus_ipc_server HTTP Server
- 6.1. REST API Endpoints
- 6.2. Server Configuration and Deployment
- 7. Build, Dependencies, and Quality Gates
- 7.1. Cargo Features and Dependency Isolation
- 7.2. Testing Strategy
- 7.2.1. Wire-v1 Golden Test Vectors
- 7.2.2. Property-Based Wire Tests
- 7.3. CI, Coverage, and Release Qualification
- 8. Project History and Licensing
- 8.1. Naming History and Completed Renames
- 8.2. Licensing
- 9. Glossary