Runtime

TinyRustLM Hostile-Artifact Hardening, Fuzzing, Differential Testing, and Formal-Invariant Program

Report summary

Label Meaning --- --- Observed public fact Directly stated in a cited public specification, official repository, advisory, or standard. Externally sourced fact Supported by public evidence but not observed in TinyRustLM itself. Inference A conclusion drawn from the supplied product context and cited

Status
Research archive item
Category
Runtime
Length
9,322 words
Reading time
43 minutes
Report type
evaluation

Key topics

  • Runtime
  • .NET
  • Rust
  • Privacy
  • Semantic Systems
  • Research Archive
  • Strategy
  • Audit

Research provenance

Archive status
Research archive item
Content identity
sha256:f396617f9425ffd1535444f3e843cd6442bd715dd4129b0dd5c568b221531efa

For citation, use the report title and canonical URL. Archival presence does not establish authorship or promote report statements into portfolio evidence.

Source availability: 48 citation markers in the source export have no recoverable source links. Those markers are omitted from this reader; any supplied bibliography and ordinary links remain. Check the original sources before relying on the cited claims.

This page renders the archived Markdown as safe, formatted HTML. It is background research and does not become a portfolio claim without evidence review.

Full report

On this page

Executive hardening strategy and assumptions

Evidence labels used throughout this report

LabelMeaning
Observed public factDirectly stated in a cited public specification, official repository, advisory, or standard.
Externally sourced factSupported by public evidence but not observed in TinyRustLM itself.
InferenceA conclusion drawn from the supplied product context and cited external evidence.
Engineering recommendationA proposed TinyRustLM design or test requirement.
AssumptionA premise adopted because private implementation evidence is unavailable.
Local verification requiredA fact that must be confirmed against authorized TinyRustLM source, builds, fixtures, or operational configuration.

Scope. The uploaded engineering brief makes the research topic specific: hardening TinyRustLM against malformed, adversarial, oversized, inconsistent, and resource-exhausting inputs across model files, manifests, receipts, tokenizer data, grammars, networking, browser/WASM boundaries, archives, and native APIs. It also fixes important constraints: safe Rust by default, bounded validation before allocation or execution, no permissive compatibility readers for unpublished formats, privacy-safe diagnostics, immutable failure evidence, and fail-atomic preservation of the last-known-good state.

Assumption. No private TinyRustLM source, parser implementations, file-format specifications, binaries, corpora, crash records, CI configuration, or operational limits were available. Consequently, this report defines implementation contracts, harness shapes, invariants, and verification gates, but it does not claim that the present product satisfies them.

Executive conclusion. TinyRustLM should treat every byte sequence crossing a trust boundary as hostile, including bytes obtained from “trusted” catalogs, local files, loopback services, same-origin browser messages, package consumers, and previously cached artifacts. Provenance can influence authorization and reputation; it cannot substitute for structural validation. Safe Rust materially reduces classes of memory corruption, but it does not prevent integer-wrap logic errors, unbounded allocation, stack exhaustion, algorithmic complexity attacks, deadlocks, semantic ambiguity, or state corruption caused by valid-but-malicious inputs. Rust’s own reference distinguishes soundness from broader application safety, and its undefined-behavior rules do not purport to prevent denial of service or business-logic failures.

The recommended architecture is a bounded admission pipeline:

untrusted bytes
    ↓
transport envelope limits
    ↓
bounded structural preflight
    ↓
canonical representation and exact-consumption check
    ↓
semantic and cross-object validation
    ↓
cryptographic identity and signature verification
    ↓
resource plan and allocation approval
    ↓
quarantined preparation
    ↓
single fail-atomic activation commit

No later phase may compensate for a missing earlier bound. Hashing an enormous attacker-selected region is still resource consumption. Verifying a signature over ambiguous serialization does not create a canonical interpretation. Loading tensor data before proving all ranges and dimensions are bounded defeats preflight. Parsing in WebAssembly does not make excessive CPU or memory use acceptable.

Primary security objectives

ObjectiveRequired property
Memory and type safetyNo out-of-bounds access, invalid references, uninitialized reads, use-after-free, ABI width confusion, or unsafe-code soundness gap.
Bounded resource useEvery input has explicit byte, item, nesting, allocation, decompression, CPU-work, wall-clock, and concurrency budgets.
Canonical interpretationOne accepted byte sequence has one meaning; duplicate or ambiguous encodings are rejected rather than “recovered.”
Fail-atomic stateCandidate parsing, validation, cancellation, or activation failure cannot mutate the active model or its composition-bound caches.
Path containmentImports and archive extraction cannot escape a designated root through textual traversal, links, reparse points, case folding, races, or platform namespaces.
Network framing safetyConflicting message lengths, duplicate framing headers, malformed chunking, ambiguous request targets, and connection-reuse residues are rejected consistently.
Diagnostic privacyPublic errors reveal bounded codes and hashes, not raw payloads, prompts, tokens, credentials, paths, or uncontrolled remote names.
Evidence integrityOriginal failures, minimized reproductions, tool identities, and regression associations are immutable and content-addressed.
Cross-runtime equivalenceNative, WASM, scalar, optimized, tokenizer, canonicalizer, and reference implementations must agree within explicitly documented numerical tolerances.

Engineering recommendation. Use a small, independently reviewed admission core containing only byte cursors, checked arithmetic, limit accounting, structural parsers, canonical encoders, and immutable validated descriptors. It should not contain network clients, GPU code, model execution, dynamic dispatch into metadata, archive extraction, or application state mutation. The core should compile for native and wasm32, with the same acceptance semantics and the same domain error codes.

Engineering recommendation. Keep production dependencies near zero as requested, but explicitly permit test-only tools. cargo-fuzz wraps libFuzzer and is the standard Rust-oriented entry point; libFuzzer expects fast, deterministic, narrow, repeatedly callable harnesses and supports corpus minimization, dictionaries, timeouts, and RSS limits. AFL++ and honggfuzz provide useful independent mutation and scheduling behavior, while Miri, Loom, Kani, sanitizers, and deductive verifiers answer different questions. None constitutes a production guarantee on its own.

Assumptions requiring ratification

AssumptionWhy it matters
.slm is unpublished and can still be changed incompatibly.Strict rejection and deletion of permissive readers are feasible without a legacy-compatibility burden.
Parsing can be separated from allocation and activation.Required for bounded preflight and fail-atomic state.
Model metadata contains no intentionally executable program.Otherwise a separate code-signing, capability, and sandbox threat model is required.
All public APIs can return stable domain error codes.Required for deterministic, privacy-safe differential testing.
Native and WASM can share a format-level conformance suite.Required to stop runtime-specific parser drift.
Archive import is optional rather than intrinsic to .slm.The preferred defense is to eliminate extraction when a direct container reader suffices.
Model-size, tensor-count, vocabulary, context, grammar, and network limits can be product-configured but not attacker-raised.Limits must be policy, not fields trusted from the artifact.

Attack surface and trust boundaries

The trust boundary is crossed when an attacker can influence bytes, lengths, ordering, identity, paths, destinations, timing, cancellation, or concurrency. A same-machine loopback socket, browser worker, package wrapper, or catalog entry is still a boundary because another process, tab, extension, compromised dependency, or stale cache can supply malformed values.

Attack-surface and trust-boundary matrix

SurfaceRepresentative hostile inputsStructural bounds required before allocationCanonical and semantic objectivesForbidden effects during parsing
.slm fixed headerTruncated magic/version, unsupported flags, extreme section counts, inconsistent declared size, polyglot prefixFixed minimum and maximum header bytes; known version set; checked declared size; section-count capOne endianness, one version interpretation, reserved bits zero, exact file-size relationNo tensor allocation, mapping, decompression, GPU creation, or active-state mutation
.slm tensor directoryDuplicate names, overlapping ranges, gaps, reversed ranges, extreme rank, product overflow, invalid dtype, quantization tailsMaximum tensors, rank, name length, dimensions, total metadata, tensor bytes and total elementsUnique identifiers; sorted or canonically sortable entries; full validated data coverage; dtype/shape/size agreementNo per-tensor buffer creation or kernel dispatch
Tensor data and quantization blocksShort final block, impossible padding, noncanonical NaNs where disallowed, offset aliasing, malicious alignmentRange inside file; checked block count and padding; aggregate byte budgetExact block layout; no hidden trailing bytes; numerical policy explicitNo SIMD/GPU access until representation is validated
Tokenizer vocabulary and mergesDuplicate tokens, invalid UTF-8, huge strings, conflicting IDs, cycles, pathological prefix setsVocabulary, token-byte, merge-rule, trie-node, and total-work capsStable byte/token mapping, unique IDs, deterministic normalization policyNo generation cache mutation
Chat templates and grammarsDeep recursion, catastrophic alternation, unsupported directives, embedded tool requests, enormous literalsGrammar node/depth/transition caps; no unbounded recursive descent; compile-work budgetPure declarative grammar; deterministic accepted language; no executable metadataNo tool invocation, filesystem, network, or prompt logging
JSON or canonical metadataDuplicate keys, long numbers, exponent extremes, invalid Unicode, key-order ambiguity, canonicalization collisionInput bytes, string bytes, members, number digits, nesting, aggregate workReject duplicate properties; define exact Unicode policy; sign canonical bytes rather than parser-dependent objectsNo environment-variable interpolation or URI fetch
Composition manifests and adaptersMissing base model, adapter cycles, tensor-shape mismatch, conflicting precedence, cache confusionMaximum components, graph nodes/edges, dependency depth, adapter bytesAcyclic composition, explicit binding to base artifact hash and compatible schemaNo active cache changes before commit
Chunk maps and range indexesOverlap, gap, duplicate chunk, integer overflow, hash mismatch, reordered chunksChunk count, individual and aggregate range capsExact coverage policy; each chunk bound to artifact identity and indexNo sparse allocation based only on remote lengths
SignaturesAlgorithm confusion, wrapped signed object, duplicate signer, signature over noncanonical representationSignature count, key ID length, signed-region lengthDomain separation; exact bytes signed; algorithm and key policy fixed externallyNo trust elevation before full semantic validation
ReceiptsReplay, duplicate logical operation, timestamp overflow, mutable prior entry, unbounded metadataReceipt bytes, entries, timestamp and duration boundsAppend-only sequence, operation-id uniqueness, prior-hash linkageNo overwrite of prior failure or success records
Grammar and schema filesReference loops, excessive $ref-like expansion, ambiguous alternatives, unknown extensionsReference count, expansion depth, total nodes and compilation stepsClosed-world schema version; unresolved references rejectNo dynamic code generation
MemoryEndpoints envelopesDestination injection, tenant confusion, huge vector/list, nested compression, replay IDEnvelope, field, item, body and decompressed-size capsEndpoint identity selected by policy; replay-resistant operation IDsNo attacker-selected network destination
Catalog metadataConfusable publisher/model names, stale signatures, unexpected redirects, huge descriptionsResponse, field, redirect, URL, and item limitsIdentity by hash and verified signer, not display nameNo automatic activation
HTTP request line and headersConflicting Content-Length/Transfer-Encoding, duplicate framing, obs-fold, oversized fields, absolute-form targetsRequest-line, total-header, field-count, field-size, body, chunk and connection-work capsOne framing interpretation; strict target form; deterministic duplicate-header rulesNo partial request dispatch
HTTP rangesReversed or overflowing ranges, excessive multipart ranges, huge suffix rangesRange count and parsed integer limits; checked inclusive/exclusive conversionNormalize to validated half-open intervals; coalesce only after authorizationNo preallocation from untrusted Content-Range
WebSocket framesInvalid opcodes, unmasked client frames, fragmented control frames, huge fragmented message, compression bombFrame, message, fragment, decompressed bytes, ratio and work capsCorrect fragment state machine; UTF-8 policy for text; negotiated extension enforcementNo unlimited reassembly
Worker and browser messagesType confusion, cloned huge arrays, stale generation IDs, reordered completion messagesMessage bytes, handles, attachments, in-flight requests, generationsSchema-tagged messages; stale generation rejected; transfer ownership explicitNo direct active-model pointer replacement
JS/WASM ABIPointer-plus-length overflow, stale view after memory growth, invalid handle, wrong alignment, signed conversionValidate pointer and length in wide integer; current memory size; handle table limitsCopy or borrow only for call lifetime; generation-tagged opaque handlesNo unchecked slice creation
C ABINull/non-null mismatch, width truncation, foreign unwind, unterminated strings, alias violationsFixed-width lengths; maximum strings; pointer ranges where verifiableExplicit ownership and lifetime; no unwinding across ABI; stable error structNo borrowed reference retained after call
.NET wrapperNegative lengths, oversized arrays, disposed handles, UTF-16 confusion, concurrent callsChecked conversion into fixed-width Rust values; wrapper-side and Rust-side capsOpaque handles and idempotent disposal; documented thread safetyNo exception crossing unmanaged boundary
Archives and packagesAbsolute paths, .., symlink/junction/hard-link escape, devices, ADS, duplicate names, zip bombEntries, names, compressed and expanded bytes, ratio, nesting and file-count capsDestination containment after resolution; regular files only unless explicitly requiredNo extraction outside fresh staging directory
Config files and CLIInclude loops, hostile paths, enormous arguments, repeated flags, response-file recursionFile, line, argument, include-depth and total-token capsClosed option set; deterministic precedence; secrets redactedNo unbounded glob expansion or remote fetch

Boundary-specific objectives

Binary artifacts. Every offset is a half-open interval [start, end) expressed in a fixed-width unsigned type until proven representable as usize. Entries must be nonoverlapping. Whether gaps are allowed must be a format-level decision; for core model data, the safer default is exact coverage so suffix polyglots and concealed secondary payloads are rejected. Safetensors illustrates several useful defensive choices: a length-delimited JSON header, disallowed duplicate keys, explicit tensor offsets, and a requirement that the tensor buffer be fully indexed without holes. Those choices are evidence that a tensor format can remain simple while imposing overlap and coverage invariants, not proof that TinyRustLM should copy the format unchanged.

Structured metadata. RFC 8785’s JSON Canonicalization Scheme requires no duplicate property names and defines a deterministic serialization, but it deliberately preserves string data rather than performing Unicode normalization. TinyRustLM must therefore choose whether identifiers are byte-exact, NFC-normalized before admission, or restricted to a conservative character subset; it must not allow one component to normalize while another signs or compares raw strings. Unicode normalization forms are stable and idempotent for their defined domains, but compatibility normalization can erase distinctions and should not be applied blindly.

Network framing. HTTP/1.1 explicitly warns that messages containing both Transfer-Encoding and Content-Length can facilitate request smuggling when recipients disagree. A strict loopback server should reject the combination and close the connection rather than rely on downstream interpretation. WebSocket receivers must enforce masking direction, fragmentation sequencing, control-frame size, and nonfragmentation rules. Per-message compression adds independent state and memory constraints, including negotiated window and context-takeover parameters.

Paths and archives. Textual prefix checks are inadequate because absolute paths, .., alternate separators, links, reparse points, namespace syntax, and time-of-check/time-of-use races can change the final target. Windows additionally has reserved names, NUL and control restrictions, alternate data streams, UNC and drive-relative forms, and symbolic links implemented as reparse points. CWE-22 recommends canonicalization and containment rather than solely filtering suspicious strings, while Microsoft’s filesystem documentation confirms the platform-specific namespace and link behavior that must be tested.

Path and archive admission contract

Engineering recommendation. Prefer reading package members directly from a validated container without extracting them. Where extraction is unavoidable:

  1. Create a new, private staging directory owned by the operation.
  2. Reject absolute, rooted, drive-relative, UNC, device, namespaced, empty, dot, parent, ADS-bearing, reserved-device, and NUL-containing member names before filesystem calls.
  3. Convert separators according to a format-defined portable path grammar rather than host interpretation.
  4. Reject symlink, junction, reparse-point, hard-link, device, FIFO, socket, and other nonregular entries unless a separately reviewed use case requires them.
  5. Open each destination relative to a directory handle using no-follow semantics where supported.
  6. After creation, resolve the actual object and verify containment under the staging root.
  7. Refuse duplicate normalized paths and case-fold collisions on case-insensitive destinations.
  8. Enforce aggregate expanded bytes, file count, directory count, per-file bytes, compression ratio, and CPU budget.
  9. Never execute, import, or dynamically load extracted scripts or libraries.
  10. Atomically publish only a fully validated staging tree; recursively delete failed staging trees using independent cleanup attempts.

Network parser test requirements

ClassRequired cases and oracle
Message framingOne Content-Length; repeated identical values; differing values; comma forms; Transfer-Encoding plus Content-Length; malformed chunk sizes; trailer overflow; extra bytes after body. Strict mode rejects ambiguity and closes reusable connections.
Header syntaxOversized name/value, excessive count, invalid control characters, prohibited obs-fold, leading whitespace, duplicate singleton headers, mixed case, empty field names.
Request targetOrigin-form only for loopback APIs unless another form is explicitly required; reject absolute-form authority injection, fragments, backslashes, NUL, malformed percent encoding, decoded dot segments and double-decoding discrepancies.
Ranges0-0, suffix zero, open-ended range, maximum integers, start greater than end, inclusive-to-exclusive overflow, overlapping and excessive multipart ranges, inconsistent Content-Range.
Body typesMultipart boundary absent, boundary prefix collision, enormous preamble/epilogue, nested multipart if unsupported, body arriving slowly, cancellation mid-body.
Connection behaviorPipelined valid and invalid requests, invalid request followed by valid bytes, body shorter or longer than declared, response completion before reuse, idle and total connection deadlines.
WebSocketMask direction, reserved bits, all length encodings, nonminimal length representation, fragmented text UTF-8 split across frames, control frame in fragments, fragmented control frame rejection, excessive fragments, close-reason UTF-8, compression expansion and context takeover.

Universal bounded reader, checked arithmetic, and fail-atomic state

Bounded-reader contract

Engineering recommendation. All binary and structured parsers should consume input through one audited cursor abstraction or equivalent generated pattern. Direct indexing into attacker-controlled buffers should be prohibited in parser modules except inside that abstraction.

#[Figure omitted from source export: forbid(unsafecode)]

#[derive(Clone, Copy, Debug)]
pub struct ParseLimits {
    pub max_input_bytes: u64,
    pub max_items: u32,
    pub max_string_bytes: u32,
    pub max_nesting: u16,
    pub max_work_units: u64,
    pub max_planned_allocation: u64,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ParseCode {
    InputTooLarge,
    UnexpectedEof,
    IntegerOverflow,
    WidthNotRepresentable,
    CountLimit,
    StringLimit,
    NestingLimit,
    WorkLimit,
    AllocationLimit,
    InvalidUtf8,
    InvalidValue,
    DuplicateField,
    Overlap,
    Gap,
    TrailingBytes,
    UnsupportedVersion,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ParseError {
    pub code: ParseCode,
    pub stage: u16,
    pub field: u16,
    pub offset_bucket: u32,
}

pub struct Reader<'a> {
    bytes: &'a [u8],
    pos: usize,
    work: u64,
    limits: ParseLimits,
}

impl<'a> Reader<'a> {
    pub fn new(bytes: &'a [u8], limits: ParseLimits) -> Result<Self, ParseError> {
        let len = u64::try_from(bytes.len()).map_err(|_| err(ParseCode::WidthNotRepresentable))?;
        if len > limits.max_input_bytes {
            return Err(err(ParseCode::InputTooLarge));
        }
        Ok(Self { bytes, pos: 0, work: 0, limits })
    }

    pub fn remaining(&self) -> usize {
        self.bytes.len() - self.pos
    }

    pub fn position(&self) -> usize {
        self.pos
    }

    pub fn charge(&mut self, units: u64) -> Result<(), ParseError> {
        self.work = self.work
            .checked_add(units)
            .ok_or_else(|| err(ParseCode::IntegerOverflow))?;
        if self.work > self.limits.max_work_units {
            return Err(err(ParseCode::WorkLimit));
        }
        Ok(())
    }

    pub fn take(&mut self, n: usize) -> Result<&'a [u8], ParseError> {
        self.charge(u64::try_from(n).map_err(|_| err(ParseCode::WidthNotRepresentable))?)?;
        let end = self.pos
            .checked_add(n)
            .ok_or_else(|| err(ParseCode::IntegerOverflow))?;
        let out = self.bytes
            .get(self.pos..end)
            .ok_or_else(|| err(ParseCode::UnexpectedEof))?;
        self.pos = end;
        Ok(out)
    }

    pub fn read_u32_le(&mut self) -> Result<u32, ParseError> {
        let b: [u8; 4] = self.take(4)?
            .try_into()
            .map_err(|_| err(ParseCode::UnexpectedEof))?;
        Ok(u32::from_le_bytes(b))
    }

    pub fn read_len_u32(&mut self, maximum: u32) -> Result<usize, ParseError> {
        let value = self.read_u32_le()?;
        if value > maximum {
            return Err(err(ParseCode::CountLimit));
        }
        usize::try_from(value).map_err(|_| err(ParseCode::WidthNotRepresentable))
    }

    pub fn finish_exact(self) -> Result<(), ParseError> {
        if self.pos != self.bytes.len() {
            return Err(err(ParseCode::TrailingBytes));
        }
        Ok(())
    }
}

const fn err(code: ParseCode) -> ParseError {
    ParseError { code, stage: 0, field: 0, offset_bucket: 0 }
}

The public error carries only bounded numeric classifications. A private diagnostic layer may associate the failure with an artifact hash, build ID, target ID, and more precise offset, but must not include raw field contents or paths by default.

Required reader rules

RuleContract
Cursor monotonicity0 ≤ old_pos ≤ new_pos ≤ input_len; no seek based on unvalidated arithmetic.
Remaining lengthDerived by subtraction only after maintaining pos ≤ len.
Checked arithmeticAll attacker-influenced addition, multiplication, shifts, alignment, and inclusive/exclusive conversion use checked operations.
Maximum countsCount checked before conversion, allocation, or iteration.
String limitsLength checked before read; UTF-8 validation occurs on the bounded slice; identifier normalization has a separate work bound.
NestingPrefer iterative stacks; otherwise decrement a hard depth budget before descent and restore it on return.
Work budgetCharge per byte scanned, item visited, comparison, graph edge, normalization step, grammar expansion, and decompressed output block.
AllocationCompute aggregate planned allocation first; compare to policy; then use try_reserve or try_reserve_exact and handle failure.
Exact consumptionCore artifacts reject trailing bytes unless the format explicitly defines an extension region with its own length and rules.
DeterminismIdentical bytes and policy produce the same success descriptor or domain error code independent of host path, locale, hash-map seed, or thread scheduling.
No parser side effectsParsing returns immutable descriptors; it cannot update active model state, caches, receipt logs, network endpoints, or filesystem destinations.

Checked-arithmetic invariant library

Rust exposes checked integer methods such as checked_add and checked_mul; using them explicitly avoids relying on profile-dependent overflow behavior. The key design rule is to retain values as fixed-width format types until bounds are proven, then convert once to the destination width. usize differs between native 64-bit and wasm32, so successful native conversion is not evidence of WASM representability.

#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct ByteCount(u64);

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct FileRange {
    pub start: u64,
    pub end: u64, // exclusive
}

impl ByteCount {
    pub fn checked_add(self, rhs: Self) -> Result<Self, ParseCode> {
        self.0.checked_add(rhs.0)
            .map(Self)
            .ok_or(ParseCode::IntegerOverflow)
    }

    pub fn checked_mul(self, rhs: u64) -> Result<Self, ParseCode> {
        self.0.checked_mul(rhs)
            .map(Self)
            .ok_or(ParseCode::IntegerOverflow)
    }

    pub fn as_usize(self) -> Result<usize, ParseCode> {
        usize::try_from(self.0).map_err(|_| ParseCode::WidthNotRepresentable)
    }
}

impl FileRange {
    pub fn new(start: u64, end: u64, file_len: u64) -> Result<Self, ParseCode> {
        if start > end || end > file_len {
            return Err(ParseCode::InvalidValue);
        }
        Ok(Self { start, end })
    }

    pub fn len(self) -> ByteCount {
        ByteCount(self.end - self.start)
    }

    pub fn overlaps(self, other: Self) -> bool {
        self.start < other.end && other.start < self.end
    }
}

pub fn checked_product(values: &[u64], maximum: u64) -> Result<u64, ParseCode> {
    let mut product = 1_u64;
    for &value in values {
        product = product
            .checked_mul(value)
            .ok_or(ParseCode::IntegerOverflow)?;
        if product > maximum {
            return Err(ParseCode::AllocationLimit);
        }
    }
    Ok(product)
}

Arithmetic proof obligations

DomainRequired proof obligation
File offsetsstart ≤ end ≤ file_len; conversion to usize only after end ≤ usize::MAX; slice expression cannot overflow.
Tensor elementselements = Π dimension; each multiplication checked; rank and each dimension bounded; zero-dimension semantics defined.
Tensor bytesbytes = ceil(elements × bits_per_element / 8) using a checked formula that cannot overflow during rounding.
StridesIf stored, each stride is representable and the maximum reachable element offset remains inside the tensor range; otherwise reject nonpacked layouts.
Quantization blocksblocks = ceil(elements / block_elements) with checked addition; blocks × bytes_per_block equals the declared tensor range after tail rules.
Alignment and paddingaligned = value.checked_add(alignment - 1)?.checked_div(alignment)?.checked_mul(alignment)?; alignment nonzero and policy-bounded.
Chunk rangesEvery range is within artifact size; sorting cannot change identity; overlaps rejected; gap policy explicit; aggregate does not overflow.
WASM pagespage_bytes = pages × 65,536 checked in u64; page count also conforms to instantiated memory maximum. WASM memory limits do not excuse application-level overcommit.
Context positionspast_tokens + requested_tokens + special_tokens ≤ context_limit; all operands converted to one width before arithmetic.
Token countsTokenizer output count bounded independently from input-byte count because short inputs can expand into many logical tokens under some schemes.
HTTP rangesParse decimal digits with checked multiply-by-ten/add; convert inclusive end to exclusive with checked_add(1); reject overflow rather than saturating.
TimestampsParse into a fixed unit and signedness; reject out-of-policy range; do not subtract untrusted timestamps without checked signed arithmetic.
DurationsConvert seconds/milliseconds/nanoseconds with checked multiplication; cap before passing to timer APIs; distinguish deadline from elapsed duration.
C ABI lengthsAccept u64 or an explicitly sized C type, reject values above both policy and usize::MAX; never silently cast negative signed lengths.
.NET lengthsReject negative values before conversion; ensure array length and supplied length agree; copy or pin only for the documented call lifetime.

Engineering recommendation. Add model-checking harnesses for each helper over small and boundary domains. Kani can prove assertions, panic absence, and arithmetic-overflow properties within bounded harnesses, but its documentation currently treats concurrency as out of scope; use it for pure arithmetic and parser helpers, not as evidence about activation races.

Parser phase separation

PhaseMay readMay allocateMay cacheMay mutate
Envelope gateTransport-declared size and a fixed prefixConstant-size stack/local buffersNothing persistentPer-request counters only
Structural preflightEntire bounded metadata and, where necessary, selected bounded data tailsBounded descriptor vectors after counts are validatedTemporary operation-local parse cacheOperation-local cursor and budget
CanonicalizationValidated textual and structural fieldsBounded canonical outputOperation-local canonical bytesNo shared state
Semantic validationImmutable descriptor graph and bounded data samplesBounded validation workspaceCandidate-local indexesCandidate object only
Identity verificationCanonical bytes and validated rangesHash state and bounded signature structuresCandidate hashCandidate object only
Resource planningDescriptor sizes and product policyA small allocation planCandidate planCandidate object only
PreparationValidated ranges and approved planQuarantined tensor buffers, mappings, GPU resourcesCandidate-local cacheCandidate resources only
Activation commitPrepared candidate and current active-state handleIdeally none beyond a small state objectNew generation-scoped cacheOne atomic or lock-protected state swap
Post-commit cleanupOld state exclusively owned after swapNo new unbounded allocationsNoneOld-state resource release and append-only receipt

Prohibition. Decompression, if supported, must occur only after a compressed-size cap, declared expanded-size cap, ratio cap, codec policy, and output budget are established. Because a compressed stream can produce far more output than input, the decompressor must write through a bounded sink rather than allocate the declared output optimistically.

Fail-atomic state model

Bytes
  └──parse──> ParsedCandidate
                 └──validate──> ValidatedCandidate
                                    └──plan──> PlannedCandidate
                                                  └──prepare──> PreparedCandidate
                                                                    └──commit──> ActiveGeneration

A type representing an earlier phase must not expose methods belonging to later phases. This typestate pattern prevents accidental activation of merely parsed data, though it does not by itself prove runtime limits or concurrency behavior.

Required state-machine properties

PropertyExecutable assertion
Validation isolationHash of active state before validation equals hash after every validation success, failure, timeout, panic containment, or cancellation.
Failed activation rollbackAny preparation or commit failure leaves the previous active generation, caches, tokenizer, adapters, and externally visible model identity byte-for-byte or semantically exact.
Single commit pointNo externally visible partial candidate state exists before one generation swap.
Cancellation idempotencecancel(cancel(op)) has the same state and result class as cancel(op); cancellation after terminal completion has no secondary effect.
Receipt append-onlyExisting receipt bytes and hashes never change; a new record references the prior chain head.
Replay uniquenessReusing one operation identifier cannot create a second logical activation or receipt.
Cache generation bindingEvery composition-sensitive cache key contains the active model/composition generation or immutable artifact hashes.
Cleanup independenceFailure releasing one owned resource does not prevent attempts to release the remaining owned resources.
Stale worker rejectionResults include an operation and generation token; a result for a superseded generation cannot publish state.
Last-known-good preservationAny rejected artifact leaves the prior active state available unless an independent fatal platform event makes it unavailable.

Engineering recommendation. Make receipt append a separate, durable finalization operation. If the product must record failed attempts, append the failure record without changing the active-state pointer. If durable receipt append itself fails, expose that as an evidence failure without retroactively reclassifying a successful in-memory activation; the exact product rule needs local ratification.

Mutation, property-based testing, coverage-guided fuzzing, and differential testing

Mutation taxonomies

FamilyMandatory mutations
Binary framingEvery single-bit flip in fixed headers; byte substitution; insertion; deletion; truncation at every offset for small seeds; extension at every boundary; repeated magic; alternate endian interpretation; polyglot prefix and suffix.
Counts and tablesZero, one, maximum allowed, maximum plus one, integer maximum; duplicate table; duplicate entry; reordered entries; unsorted but otherwise valid entries; count smaller or larger than supplied entries.
RangesStart equals end; start greater than end; end equals file length; end one past file; overlap by one byte and full containment; duplicate range; gap; arithmetic wrap; aliased tensor names to same range.
Dimensions and tensorsRank zero, one and maximum; dimensions zero and one; one extreme dimension; multiple dimensions whose product overflows; element count valid but byte count overflows; invalid dtype; unsupported block size; malformed quantization tail; padding with nonzero bytes.
Checksums and signaturesCorrect checksum on wrong section, swapped checksums, duplicate signatures, changed canonical order after signing, signature wrapper with unsigned outer fields, unknown algorithm, key-ID confusable.
Allocation bombsSmall file declaring huge sparse dimensions; enormous count of zero-length entries; many tiny strings; deeply nested but byte-small structures; internally consistent dimensions exceeding policy; high decompression ratio.
Structured syntaxDuplicate keys before and after normalization; unknown, missing and null fields; type confusion; long integer and decimal strings; exponent extremes; negative zero; forbidden NaN or infinity spellings; invalid UTF-8; overlong or surrogate-like invalid encodings where applicable.
UnicodeNFC/NFD equivalents; compatibility equivalents; combining-mark runs; bidi controls; confusable identifiers; case-fold collisions; separator-like characters; noncharacters if policy rejects them; strings crossing normalization boundaries.
CanonicalizationKey reordering; insignificant whitespace; alternate escape spelling; number spelling variants; strings whose normalization policy differs; canonicalization idempotence; sign-then-reencode disagreement.
NetworkConflicting lengths, duplicate headers, prohibited folding, malformed chunks, partial reads at every byte, pipelining, connection residue, range overflow, multipart boundary collision, WebSocket fragmentation and compressed expansion.
Paths and archives/, \, mixed separators, .., repeated dots, percent-encoded traversal, absolute and drive-relative paths, UNC and extended namespaces, ADS, reserved devices, trailing dots/spaces, case collisions, link entries, extraction replacement races.
ABI and browserNull pointer with nonzero length; nonnull with impossible length; pointer-plus-length wrap; stale handle; disposed handle; detached view; memory growth during call; wrong thread; worker result after cancellation; duplicated transferable.

Property-based generator design

Property-based testing should generate both accepted structures and near-valid rejected structures. QuickCheck established the model of generated inputs and shrinking counterexamples, while later work combines property generation with coverage feedback. TinyRustLM need not make any such library a runtime dependency; generators belong in test-only modules.

Valid generators

GeneratorConstruction strategy
Minimal .slmStart from the smallest legal header, one scalar or empty tensor if permitted, and exact data coverage.
Tensor graphGenerate bounded rank/dimensions, compute bytes with the same independent mathematical specification, then place nonoverlapping ranges.
TokenizerGenerate a bijection or documented many-to-one mapping with unique IDs and bounded byte strings.
Manifest graphGenerate a directed acyclic graph by selecting edges only from newer to older nodes.
Canonical metadataGenerate semantic objects first, then serialize with a reference canonical encoder.
Receipt chainGenerate operation IDs, prior hashes, bounded timestamps, and terminal outcomes.
HTTP/WebSocketGenerate messages from an independent grammar with configurable read fragmentation.
ArchiveGenerate portable relative paths and regular files inside aggregate quotas.
ABI callsGenerate valid handle-table states and pointer/length pairs referencing an owned bounded region.

Invalid near-valid generators. Begin with one valid generated object and violate exactly one named invariant: one duplicate key, one overlapping range, one incorrect tensor byte, one stale generation, one invalid range endpoint, one extra trailing byte, or one cancellation reordering. These generators provide clearer blame and better shrinking than wholly random invalid data.

Shrink strategy

Input kindShrinking order
BinaryRemove unrelated sections; reduce table entries; shrink values toward {0, 1, limit, limit+1, max}; shorten names; move corruption toward earliest necessary byte.
StructuredRemove unrelated properties; reduce depth; simplify Unicode while preserving the collision; shorten numbers and arrays; retain duplicate pair.
State sequenceRemove operations; shorten concurrency schedule; reduce to two actors; replace unrelated successes with no-ops; minimize to the first invariant violation.
NetworkReduce connections, requests, headers, chunks and fragmentation points; preserve the framing disagreement.
ArchiveRemove members; shorten paths; reduce to one escaping member and the minimum necessary link or separator behavior.

Metamorphic and round-trip properties

PropertyRequired result
Parse–encode–parseA valid semantic object encoded canonically and parsed again yields the same semantic object.
Canonical idempotencecanon(canon(x)) = canon(x).
ReorderingReordering fields declared unordered does not change the semantic descriptor or hash of canonical bytes.
Trailing dataAdding any undefined byte to a complete core artifact changes acceptance to a deterministic trailing-data rejection.
Chunk partitioningFeeding identical bytes under every possible bounded read fragmentation produces the same result.
Native/WASMBoth builds produce the same acceptance and domain error code for every corpus item.
Allocation ceilingPeak planned and actual operation-owned bytes remain below the configured bound for all generated inputs.
Work ceilingInstrumented parser work units never exceed the budget without returning WorkLimit.
Failed candidateFor every generated invalid candidate, active-state fingerprint is unchanged.
Hash localityChanging a signed semantic field changes canonical bytes and artifact/signature verification outcome.
Receipt replayReplaying an accepted operation ID creates no second state transition or logical receipt.
CancellationCancellation inserted at any yield point preserves the active generation and remains idempotent.

Coverage-guided target matrix

libFuzzer guidance recommends narrow, deterministic, fast targets that tolerate arbitrary input, avoid uncontrolled global state, and join any threads before returning. AFL++ guidance similarly favors source-level persistent harnesses and discourages fuzzing real network services when the protocol parser can instead consume an in-memory byte stream.

TargetEntry pointSuccess-side actionMaximum fuzz inputSpecial seeds and dictionary
slm_headerparse_header(&[u8], limits)Re-encode canonical header and compareHeader maximum plus small suffixMagic, versions, flag masks, endian boundaries
slm_tensor_directoryparse_directory(&[u8], file_len, limits)Validate sorted ranges and size equationsMetadata maximumDtypes, field tags, dimension boundaries
slm_preflightFull structural preflight over bounded virtual fileConstruct immutable descriptor onlySmall campaign and separately large-file campaignMinimal full files, zero-rank and empty tensors
quant_block_tailValidate one tensor’s block layoutCompare scalar size oracleSmallBlock sizes, padding patterns
tokenizerParse tokenizer bytesEncode/decode bounded sample tokensTokenizer metadata maximumUTF-8 boundaries, merge delimiters
chat_templateParse/compile declarative templateExecute only against inert symbolic data with step capTemplate maximumDirective names and delimiters
json_metadataStrict JSON subset parseCanonical encode with independent encoderMetadata maximumStructural tokens, escapes, exponent markers
manifestParse and graph-validateTopological order and hash bindingManifest maximumComponent field names and version tags
adapter_mapParse adapter descriptorsShape compatibility oracleSmallAdapter kinds and tensor names
chunk_mapParse range mapCompare interval-set oracleSmallRange syntax and hash tags
signature_envelopeParse signed envelopeExtract exactly signed bytes; no live key use requiredSmallAlgorithms, key-ID fields
receiptParse and validate receipt chainCompare append/replay modelSmallOutcome and operation tags
grammar_schemaParse/compile with step counterEnumerate only bounded tiny languageSmallGrammar operators and schema keywords
memory_endpoint_envelopeParse payload envelopeValidate destination is policy-selectedEnvelope maximumField names, operation versions
catalog_metadataParse one catalog record/pageCanonical record hashPage maximumURL and identity field names
http_requestConsume fragmented byte streamProduce normalized request descriptor onlyHeader/body test capHTTP methods, headers, CRLF, chunk tokens
http_rangesParse Range/Content-RangeCompare independent interval oracleSmallbytes=, comma, dash, digit runs
websocket_framesFrame-state machine over byte chunksDeliver to bounded sinkMessage test capOpcodes, mask bits, length sentinels
worker_messageDecode tagged messageState-model transition onlyMessage capMessage tags, generation IDs
wasm_abiValidate numeric pointer/length against synthetic memoryCopy bounded bytes to isolated bufferSmall structured inputWidth boundaries and handle tags
c_abiDecode serialized call description, not real arbitrary pointerExercise checked conversion and handle tableSmallSigned/unsigned extrema
dotnet_wrapper_contractModel wrapper call sequenceCompare reference lifecycle modelSmallDispose/cancel/call operation tags
archive_indexParse member metadata without extractionPortable path normalization and collision setArchive-header capSeparators, drive and link tokens
config_cliParse bounded argument/config tokensCanonical configuration objectSmallOption names, quoting and include syntax
parse_to_validateParse then semantic validateNo allocation beyond candidate capPer-format capCombined corpus
validate_to_planValidated descriptor to resource planAssert exact plan equations and ceilingStructured generator preferredLimit boundaries

Harness rules

A target must not access a live socket, production catalog, user directory, GPU, cloud memory service, real model execution, environment credentials, clipboard, or prompt history. It must reset operation-local state after every call and have no data-dependent logging. Any required hash key should be a fixed public test key. Time and randomness must derive only from the input or a fixed seed.

Corpus strategy

Corpus tierContents
Specification seedsOne minimal and one feature-complete valid example for each supported format version.
Boundary seedsEvery integer width boundary, empty/one/maximum count, rank, length, range and nesting boundary.
Invalid single-field seedsExactly one violation per invariant and per public error code.
Differential seedsEvery input that ever caused implementations, platforms, optimization levels, or encoders to disagree.
Historical regressionMinimized generic reproductions of fixed failures; sensitive originals remain in restricted storage.
Cross-engine corpusPeriodically merged and minimized findings from libFuzzer, AFL++, honggfuzz and structured generators.
Real quarantined artifactsAuthorized public or synthetic models stripped of private metadata; used only in isolated large-artifact campaigns.

cargo-fuzz supports target execution, input minimization, corpus minimization, and coverage reporting. libFuzzer supports dictionaries, RSS and timeout controls, and reusable corpus directories; AFL++ supports dictionary-assisted campaigns and independent scheduling. Tool versions, compiler versions, target hashes, and corpora should be pinned so evidence is reproducible.

Differential testing and disagreement adjudication

Differential testing compares independent implementations to expose inconsistencies. The oracle is not “whatever most implementations do”: an observed disagreement starts an investigation against the format specification, arithmetic model, and platform semantics. An implementation can be consistently wrong, and two implementations can share a bug.

ComparisonInputsEquality ruleAdjudication
Scalar vs optimized kernelsBounded valid tensors, boundary quantization tails, NaNs/infinities under policyBit exact where specified; otherwise documented absolute/relative/ULP envelopeScalar is not automatically correct; reduce case and inspect mathematical spec
Two canonical encodersSemantic metadata objects and accepted parsed objectsByte exactReject signing support until one encoder is proved nonconforming and fixed
Native vs WASM parserEntire shared parser corpusSame accept/reject and same domain error codeWidth-dependent acceptance is a security bug unless format explicitly differs
Source tokenizer vs Rust tokenizerRaw strings and byte sequencesSame token IDs, offsets, normalization and decodeIdentify Unicode/version/config discrepancy; never silently choose one
Public reference model vs .slmAuthorized known model and bounded promptsTensor-by-tensor import identity plus output toleranceSeparate format conversion, kernel, tokenizer and sampling layers
HTTP parser vs standards suitesRFC and established smuggling test vectorsStrictly one normalized framing or rejectionPrefer rejection when the protocol permits strict behavior
Archive validation on Windows and LinuxSame member index and synthetic extraction planSame portable accept/reject; platform may add stricter rejectionPortable format rules must be at least as strict as either destination
Debug vs releaseEntire regression and fuzz corpusSame semantic result and error codeAny overflow/profile dependence is a defect
Little-endian hosts and simulated conversionGenerated numeric fieldsSame semantic descriptorDirect host-endian reinterpretation is a defect
Browser enginesWorker/WASM/WebGPU failure corpusSame TinyRustLM state result; browser diagnostics may differNormalize only at application error boundary

Engineering recommendation. Maintain an oracle hierarchy: written format contract, mathematical invariant, independent simple reference implementation, standards conformance suites, and only then production implementations. Every disagreement record should contain both implementation identities, target and corpus hashes, minimized input hash, outputs, applicable tolerance, and the decision explaining which side changed.

Formal methods, concurrency, sanitizers, browser, WASM, and WebGPU

Risk-targeted formal techniques

TechniqueBest TinyRustLM useEvidence obtainedImportant limitation
Exhaustive testing over small domainsCursor movement, interval overlap, alignment, range conversion, tiny state machinesAll values/schedules inside the chosen finite bound were testedSays nothing beyond the bound
Kani bounded model checkingChecked arithmetic, parser helper assertions, panic freedom, option/result transitionsProof or counterexample for the bounded harnessConcurrent execution is currently out of scope; loop bounds and tool support matter.
LoomActivation commit, cancellation, receipt append, cache replacement, shutdownExplores many thread interleavings and atomic outcomes under its modelIt does not implement the full C11 model and can both raise false alarms and miss certain executions.
MiriUnsafe/FFI boundary tests if any, aliasing, invalid values, selected race behaviorDetects many forms of undefined behavior in executed pathsIt explores only executions run, has limited platform/FFI/network support, and recommends specialized tools such as Loom for complex atomics.
ASan and LSanNative parser harnesses, FFI shims, optimized kernels, C reference codeDetects many memory violations and leaks in instrumented executionDynamic and path-dependent; incomplete instrumentation reduces evidence.
TSanNative concurrent integration and wrapper testsDetects many data races in exercised schedulesRequires synchronization visibility and has unsupported constructs such as some fence use; dynamic only.
UBSanC/C++ reference parsers, shims or kernels compiled by ClangDetects selected C/C++ undefined operationsRust’s documented sanitizer interface does not provide a general -Zsanitizer=undefined; do not present C/C++ UBSan as proof about pure Rust.
Creusot or PrustiStable high-value pure helpers and state transitions with contractsDeductive proof of specified pre/postconditions and invariantsTool maturity, supported Rust subset, annotation maintenance and specification correctness limit assurance.
Typestate and capabilitiesEnforce parse/validate/prepare/activate sequencing and resource ownershipCompile-time exclusion of certain invalid API call sequencesDoes not prove bounds, absence of logic defects, or correct external effects
Manual proof notesFormat layout, commit protocol and ABI ownership rulesReviewable argument tied to code and testsCan become stale; must be versioned and checked in review
Parser-combinator proofsOnly if a small stable grammar and proof-capable library are justifiedCompositional parsing claimsLikely conflicts with zero-dependency preference and may add maintenance risk

Engineering recommendation. Formalize only high-value, low-churn kernels first:

  • checked_product, range construction, overlap detection, alignment, and u64 → usize conversion.
  • Tensor byte-size equations for every dtype and quantization scheme.
  • Canonical metadata encoding.
  • Receipt-chain append and replay rules.
  • Activation generation swap and stale-result rejection.
  • WASM and C ABI pointer/length checks.

Avoid attempting whole-product formal verification before the format and state architecture stabilize. Proof effort attached to a changing permissive parser would preserve the wrong design.

Concurrency and race testing

ScenarioActors and schedule pointsRequired invariant
Activation versus activationTwo prepared candidates race at precommit, generation allocation and state swapExactly one expected winner under policy; loser cannot partially publish
Validation versus active readsReader holds old active handle while candidate validates and commitsOld handle remains valid for its documented lifetime
Cancellation versus preparationCancel before allocation, during chunk copy, GPU preparation and immediately before commitNo commit after acknowledged cancellation unless contract explicitly declares commit already linearized
Multi-tab coordinationTwo tabs acquire, lose and recover a shared model/download lock; one tab crashesNo duplicate logical operation and no permanently orphaned lock
OPFS handle lifecycleOpen/read/replace/close interleavings with worker deathNo stale file version promoted and no unbounded handle leak
Cache replacementReaders access old cache while new generation publishes replacementCache entries are generation-bound; old cache is released only after ownership ends
Two P2P lanesBoth read shared immutable chunks while one cancels or reports corruptionImmutable data remains immutable; corruption invalidates the correct artifact identity
Receipt appendTwo terminal operations append concurrentlyChain remains linear or uses a specified merge structure; no record overwrite
Service shutdownShutdown races with requests, model switch, receipt append and cleanupNew operations rejected; owned resources all receive cleanup attempts
Browser worker resultWorker terminates or replies after page cancellation/restartStale result cannot reactivate state

Engineering recommendation. Put synchronization behind a small adapter that can use standard primitives in production and Loom primitives under cfg(loom). Keep model tests to two or three actors and short state sequences so state-space exploration remains tractable. Then supplement deterministic model checking with repeated native stress and TSan runs.

Native dynamic-analysis matrix

ConfigurationScopeFrequencyAcceptance criterion
Debug with overflow checks and assertionsAll parser, validator and state testsEvery pull requestNo panic except tests explicitly asserting panic containment
Release with overflow checks explicitly retained for security modulesParser and arithmetic corpusEvery pull requestSame result as debug
ASan plus leak detectionFuzz targets, FFI, optimized kernelsNightly Linux x86-64; scheduled arm64 where supportedNo sanitizer finding; leak exclusions documented and minimal
TSanActivation, cancellation, wrappers, receipt and shutdown testsWeekly Linux/macOS supported targetsNo unexplained report
Miri with multiple seeds and layout randomization where applicableSmall pure and ownership testsNightly or weeklyNo UB report; unsupported tests separately classified
C/C++ UBSan plus ASanAny reference kernels, shims or differential parsersNightlyNo report in exercised paths
Process memory and CPU limitsEvery long fuzz campaignEvery campaignOOM/timeout reproducer preserved and classified
Small stackRecursive or grammar-related suitesNightlyClean bounded rejection rather than stack overflow
Windows native testsPaths, archives, C/.NET ABI, lifecycleEvery Windows CI cycleSame portable parser result plus platform-strict rejection
Linux arm64Parsers, scalar/optimized differential, fuzz replayNightly or releaseNo architecture-specific disagreement

The Rust sanitizer documentation describes ASan and TSan as test/fuzzing tools, lists target-specific support, and notes that sanitizers add overhead and cannot catch every issue. cargo-fuzz itself requires LLVM sanitizer support and is documented for x86-64 and AArch64 Unix-like systems rather than Windows, so Windows assurance must include deterministic corpus replay, platform-native tests, and optionally a separate compatible fuzz engine or cross-compiled harness strategy.

Browser, WASM, and WebGPU test matrix

FaultTest injectionRequired TinyRustLM behavior
Pointer-plus-length overflowCall exported function with endpoints near 32-bit maximumReject before constructing a Rust slice
Pointer outside memoryStart equal to or greater than current byte lengthStable ABI error; no trap relied upon as normal validation
Stale typed-array viewRetain JS view, grow memory, then attempt reuseWrapper reacquires current view or rejects generation mismatch
Memory growth during operationTrigger bounded growth between descriptor validation and copyOperation either owns a copied buffer or revalidates current memory
Stale opaque handleUse freed handle or previous generation handleDeterministic invalid-handle error
Double releaseRelease the same handle twiceIdempotent bounded error or documented no-op
Detached or transferred bufferTransfer to worker or detach before callReject without exposing stale data
Worker deathTerminate worker at each state-machine yield pointActive state preserved; candidate resources reclaimed or reaped
WASM trapInject trap in preparation or kernel test moduleConvert to bounded operation failure; preserve prior state
Page cancellationCancel navigation or operation during fetch, parse and commitNo stale callback publishes candidate
Browser process restartPersist candidate or active metadata, restart, then recoverOnly fully committed, hash-verified state is recovered
WebGPU validation errorSupply invalid resource parameters through test adapterCandidate activation fails without poisoning previous model
WebGPU device lossLose device before and during dispatchDevice resources invalidated; model state either falls back safely or reports unavailable without metadata leakage
Oversized host messagePost a huge structured-clone object or fragmented sequenceHost-side envelope rejection before WASM copy
Multi-tab raceSimultaneous import, activation and evictionOperation IDs and generation locks prevent duplicate publication

WebAssembly memories are page-based and exposed through JavaScript buffers. Memory growth can replace or detach prior fixed-length views, so JS wrappers cannot retain unversioned typed-array views across growth. WebGPU devices can be lost asynchronously; the specification advises applications to handle the loss, notes that resources from the old device must be recreated, and warns that implementation-defined loss messages should not be parsed or disclose unnecessary system information.

Engineering recommendation. Treat browser error messages and GPU validation text as untrusted diagnostics. Map them to TinyRustLM domain codes and store only a bounded hash or locally restricted detail record. Never return raw implementation-defined GPU or browser strings through public receipts.

Evidence retention, triage, CI, and staged security TDD

Resource isolation and campaign controls

Engineering recommendation. Long-running fuzzing and adversarial integration tests should execute in disposable child processes or containers with:

  • A read-only build and seed corpus.
  • A fresh writable artifact directory with no user data.
  • No credentials, production endpoints, prompt history, SSH agents, cloud metadata access, or developer home-directory mounts.
  • CPU time, wall time, resident memory, address-space, open-file, process, output-size and stack limits.
  • Network disabled unless a specific isolated protocol integration test requires it.
  • Deterministic locale, timezone, environment, and test keys.
  • Crash artifacts named by cryptographic content hash rather than input-derived names.

libFuzzer provides per-input timeout, RSS, single-allocation and total-time controls, while AFL++ recommends explicit memory and timeout limits for pathological inputs. These are harness containment mechanisms, not substitutes for in-product bounds.

Privacy-safe evidence schema

CampaignRecord
  campaign_id
  tool_name
  tool_version_or_commit
  compiler_version
  target_name
  target_binary_hash
  source_revision
  corpus_manifest_hash
  dictionary_hash
  deterministic_seed
  start_time
  duration
  execution_count
  coverage_summary
  sanitizer_mode
  platform_and_architecture
  configured_limits

FailureRecord
  original_input_hash
  restricted_blob_location
  failure_class
  domain_error_or_signal
  bounded_stack_signature_hash
  target_hash
  first_seen_campaign
  minimized_input_hash
  minimizer_identity
  fix_revision
  regression_test_id
  disclosure_status

A bounded stack signature should contain normalized module/function identifiers and a small frame count, not full local paths, command lines, payload fragments, prompts, remote peer names, or environment variables. Public reports should describe the invariant and impact and may omit malicious bytes entirely.

Triage taxonomy

ClassDefinitionRequired action
Reproducible vulnerabilityInput violates a security objective such as memory safety, containment, fail-atomic state, trust binding, or privacyPreserve original; isolate; assess exposure; fix or rewrite; security review; separately authorize disclosure
Resource exhaustionInput exceeds intended CPU, memory, stack, file, handle or concurrency limits without bounded rejectionAdd or correct budget; regression test resource ceiling; rerun adjacent parsers
Numerical mismatchIndependent implementations exceed defined toleranceReduce; identify conversion, kernel or tolerance defect; block affected release path
Parser ambiguityTwo components assign different boundaries, fields or meaningTreat as security defect; tighten grammar or delete permissive path
Expected rejectionInput is invalid and rejected within all budgets with the expected stable codeAdd to corpus only if it contributes coverage or boundary evidence
Harness defectFailure arises from illegal harness state, leaked global state or incorrect oracleFix harness; rerun all findings produced by affected harness version
Flaky infrastructureNonreproducible external worker, filesystem, timing or CI failurePreserve logs and environment hash; do not close as product-safe until classified
Tool limitationUnsupported instruction, API, target or model caused tool failureRecord limitation; use another technique; never reinterpret as a pass

Immutable regression workflow

detect
  → content-address original bytes in restricted storage
  → reproduce under pinned target and tool
  → classify preliminary impact
  → minimize a copy, never the original
  → derive a generic nonsensitive regression where possible
  → fix narrowly or replace the parser/design
  → link fix, original hash, minimized hash and regression
  → rerun all invalidated phases and sibling implementations
  → authorize disclosure independently

Engineering recommendation. Failure records are append-only. A later determination such as “harness defect” adds a superseding classification record; it does not overwrite the original observation. This preserves auditability and satisfies the requirement that rejected artifacts remain traceable by hashes and bounded metadata.

CI schedule and coverage gates

CadenceWorkloadProvisional budget
Every commitUnit tests, checked-arithmetic exhaustive small domains, parser regressions, canonical round trips, single-field corruptions, native/WASM corpus replayMinutes; deterministic
Pull requestProperty tests, state-machine tests, release/debug differential, selected Kani proofs, archive/path matrix for affected codeRoughly one bounded CI job per risk area
NightlyAll fuzz targets under libFuzzer, ASan/LSan, browser worker/WASM fault suite, Miri-selected testsAt least 15 minutes per normal target; 60 minutes for top-risk parsers
WeeklyAFL++ or honggfuzz cross-engine campaigns, Loom schedules, TSan, Windows path/archive/.NET, Linux arm64, tokenizer/model differentialApproximately 6 hours for high-risk targets
Release candidateClean corpus rebuild, full minimized regression set, 24-hour campaigns for .slm, HTTP, archive, tokenizer and ABI targets, quarantined real artifacts, multi-browser restart/device-loss testsDedicated isolated workers
Post-format changeRegenerate seeds, mutation matrix and canonical corpus; rerun every parser and differential laneMandatory before merge or format publication

Provisional parser-module gates

GateRequirement
Invariant coverageEvery written structural and arithmetic invariant has at least one valid and one violating test.
Error coverageEvery public parser error code is reached by a deterministic test.
Single-field corruptionEvery fixed header field and table field is independently corrupted, truncated and boundary-tested.
Branch coverageTarget at least 85% branch and 90% line coverage for admission modules, with no unreviewed uncovered input-dependent branch. Numeric thresholds are secondary to branch review.
Fuzz target presenceEvery untrusted parser and parser-to-validator transition has a pure bounded target.
Cross-runtimeShared corpus produces identical native and WASM admission results.
Resource assertionsTests measure and enforce parser work, allocation plan, nesting and output ceilings.
Sanitizer and MiriNo unexplained finding in supported configurations.
DifferentialNo unresolved disagreement.
State atomicityFault injection at each phase leaves active-state fingerprint unchanged until commit.

Stop rules. A campaign stops when its fixed budget expires, the target or source hash changes, containment fails, or a reproducible finding requires triage. Coverage plateau is a reason to rotate dictionaries, seeds, structured mutators or engines—not evidence that the target is safe. A target with no new coverage for a day should be reviewed for unreachable guarded paths, poor seed quality, excessive rejection before deep logic, or missing structured mutations. AFL++ likewise cautions that full coverage is generally unattainable and that prolonged plateaus may call for a different fuzzer or mutator.

Staged security TDD backlog

gantt
    title TinyRustLM hostile-input hardening sequence
    dateFormat  YYYY-MM-DD
    axisFormat  %b %d

    section Admission core
    Inventory formats and set policy limits           :a1, 2026-08-03, 7d
    Checked arithmetic and interval library           :a2, after a1, 10d
    Universal bounded reader and error taxonomy       :a3, after a1, 10d
    Pure structural parsers                           :a4, after a2, 20d

    section Test foundations
    Valid and near-valid generators                   :b1, after a3, 14d
    Single-field corruption matrix                    :b2, after a4, 14d
    Metamorphic and canonicalization properties       :b3, after b1, 14d
    Corpus and immutable evidence store               :b4, after b1, 10d

    section Adversarial testing
    Coverage-guided parser targets                    :c1, after b2, 21d
    Differential native and WASM lanes                :c2, after b3, 14d
    HTTP WebSocket archive and ABI campaigns          :c3, after c1, 21d

    section State and concurrency
    Fail-atomic activation model                      :d1, after a4, 14d
    State-machine property tests                      :d2, after d1, 14d
    Loom TSan and repeated stress                     :d3, after d2, 21d

    section Dynamic and formal evidence
    ASan Miri and platform matrix                     :e1, after c1, 14d
    Kani arithmetic and range proofs                  :e2, after a2, 21d
    Browser WASM WebGPU fault injection               :e3, after c2, 21d

    section Release hardening
    Quarantined real-artifact campaigns               :f1, after c3, 14d
    Coverage review and permissive-path deletion      :f2, after e3, 14d
    Publication security gate                         :f3, after f2, 7d

Backlog sequence

StageRequired tests before implementation proceeds
ArithmeticBoundary examples first, then implementation, exhaustive small-domain checks, Kani harnesses and cross-width tests.
Pure parsersMinimal valid seed, every truncation, every field corruption, exact-consumption and work-budget assertions.
Semantic validatorsOne invariant at a time, near-valid generator, independent reference calculation, no side effects.
Property layerValid generation, invalid-near-valid generation, shrinker, canonical and metamorphic properties.
FuzzingOne target per parser, dictionaries, corpus manifest, smoke replay, nightly campaign.
State machinesReference model, operation sequences, cancellation and replay, fault injection before concurrency.
ConcurrencyLoom for minimal model, repeated stress, TSan, worker and multi-tab tests.
Dynamic analysisASan/LSan, Miri, C/C++ UBSan where applicable, small stack, process limits.
Browser/WASMABI widths, detached views, worker death, restart, traps, device loss.
Package/archivePortable path grammar, Windows-specific namespace tests, link and extraction-race tests.
Real artifactsOnly after synthetic invariants pass; execute in quarantine; no credentials or user data.

Clean deletion rules

Because TinyRustLM is pre-publication, strict redesign should replace permissive readers rather than accumulate fallback modes.

A parsing path must be deleted when any of the following holds:

  • It accepts inputs the normative writer cannot produce without a documented extension mechanism.
  • It tolerates duplicate keys, overlapping ranges, trailing bytes, ambiguous lengths, unknown executable metadata, or lossy canonicalization.
  • It performs allocation, decompression, mapping, GPU work, or state mutation before bounded structural validation.
  • It has parser semantics different from native/WASM or from the canonical encoder.
  • It exists only for malformed unpublished artifacts.
  • Its safety argument depends on provenance rather than bytes.
  • Its error path exposes uncontrolled input.

Before deletion, preserve the design decision, relevant failure hashes, test cases, and replacement revision. Delete production code, feature flags, dead tests that assert permissive acceptance, fixtures whose only purpose is compatibility with malformed unpublished output, and documentation suggesting fallback behavior. Retain generic rejection regressions and immutable evidence.

The main security dashboard should not emphasize raw execution count alone. A useful chart is a stacked coverage-and-rejection trend per parser target: new edges, stable edges, valid admissions, expected bounded rejections, timeouts, OOMs, crashes, and unresolved disagreements by campaign revision. A second useful visualization is an invariant heat map with parsers as rows and test techniques—unit, property, fuzz, differential, Kani, Miri, sanitizer, Loom, browser—as columns. A parser with high line coverage but no resource-bound or state-atomicity evidence should remain visibly incomplete.

Unknowns requiring private inspection and annotated primary-source bibliography

Facts requiring local or authorized verification

UnknownEvidence neededSecurity decision affected
Actual .slm byte layout, versioning and extension mechanismNormative format document, writer and parser source, golden filesExact bounds, trailing-byte policy, canonical encoding, target dictionaries
Tensor dtype and quantization equationsKernel and packer source, reference math, fixturesElement/byte invariants and differential tolerances
Presence of memory mapping or zero-copy slicesLoader source and platform implementationLifetime, alignment, mutation and file-replacement risks
Any unsafe in workspace or dependenciescargo geiger-style inventory or direct source audit, dependency lockfileMiri/ASan priority and soundness review
Dependency policy in production and test workspacesCargo manifests and lockfilesPinning, supply-chain review and test-tool isolation
JSON parser duplicate-key behaviorParser configuration and testsSignature and canonicalization safety
Unicode policy for model, tensor, token and publisher namesProduct specification and UI requirementsNormalization, confusable and collision rules
Signature envelope and signed bytesCryptographic specification and implementationWrapping and algorithm-confusion defenses
Receipt durability and concurrency modelStorage schema and append implementationReplay, immutability and crash consistency
Activation commit mechanismRuntime state ownership and synchronization sourceFail-atomicity and Loom model
Cache key compositionCache source and invalidation testsCross-model data reuse
HTTP implementation and proxy exposureServer/library source and deployment topologySmuggling and absolute-form risk
WebSocket compression configurationHandshake and frame implementationExpansion, context and memory limits
Browser worker and OPFS architectureJS/TS and WASM glue sourceStale views, generation, multi-tab and recovery tests
WebGPU use and fallback behaviorAdapter/device/resource lifecycle sourceDevice-loss state contract
C and .NET exported signaturesGenerated headers, wrapper source, ownership docsABI width, unwind and lifetime tests
Archive formats and extraction libraryImport source and platform codeLink, traversal, race and decompression defenses
P2P protocol framing and replay controlsProtocol spec and state-machine sourceTarget matrix and operation identity
Hosted-memory destination selectionEndpoint configuration and authorization sourceSSRF/destination-injection controls
Operational product limitsProduct requirements and benchmark dataConcrete maximum bytes, counts, work and deadlines
Existing corpus and incidentsAuthorized crashes, bug tracker and telemetry schemaPrioritization and regression preservation

Annotated primary-source bibliography

All web sources below were retrieved on August 1, 2026. Live documentation and repositories should be pinned to a commit, release, compiler toolchain, or dated specification in TinyRustLM’s evidence manifest.

  1. Rust Reference, “Behavior considered undefined.” Defines Rust soundness obligations and explicitly notes that unsafe does not relax undefined-behavior rules. It should ground any exceptional future proposal to introduce unsafe code. Official Rust Reference.
  1. Rust standard-library integer documentation. Documents checked integer operations used by the proposed arithmetic layer. The implementation should pin the actual Rust toolchain and test both 64-bit native and 32-bit WASM targets. Official @@MKREPORTTOKEN0@@ documentation.
  1. Rust Fuzz Book and cargo-fuzz. Official Rust fuzzing guidance and repository for libFuzzer-based Cargo targets, corpus minimization and coverage. The repository notes Unix-like x86-64/AArch64 and nightly/LLVM requirements. Rust Fuzz Book and @@MKREPORTTOKEN1@@ repository.
  1. LLVM libFuzzer documentation. Primary documentation for deterministic in-process targets, corpus operation, dictionaries, timeouts, RSS limits, minimization and fork mode. LLVM libFuzzer.
  1. AFL++ documentation and repository. Primary source for persistent harnesses, corpus minimization, dictionaries, independent scheduling and resource controls. The repository reported release 4.40c in March 2026 when retrieved. AFL++ repository and fuzzing-in-depth guide.
  1. honggfuzz repository. Primary repository for a separate feedback-driven, persistent-capable fuzzer useful as a cross-engine check. honggfuzz.
  1. Rust sanitizer documentation. Documents supported sanitizer modes, targets, instrumentation caveats and the distinction between testing tools and production protections. Rust Unstable Book sanitizer chapter.
  1. Miri repository. Primary documentation for Rust UB detection, supported checks and limitations regarding FFI, networking, nondeterminism and concurrency exploration. Miri.
  1. Loom repository. Primary documentation for concurrency permutation testing and its incomplete C11 modeling limitations. Loom.
  1. Kani Rust Verifier. Primary documentation for bounded model checking, panic and overflow checks, contracts and concrete counterexamples; its feature-support page states that concurrency is outside current scope. Kani book and feature support.
  1. Creusot and Prusti documentation. Primary project sources for contract-based deductive verification of Rust. These are candidates for stable arithmetic and state kernels, not automatic whole-product guarantees. Creusot User Guide and Prusti repository.
  1. RFC 9112, HTTP/1.1. Normative treatment of message framing and the security risk of simultaneous Transfer-Encoding and Content-Length. RFC 9112.
  1. RFC 9110, HTTP Semantics. Normative URI, request-target, range and semantic framework. RFC 9110.
  1. RFC 6455 and RFC 7692. Normative WebSocket framing, masking, fragmentation, control-frame and per-message compression rules. RFC 6455 and RFC 7692.
  1. RFC 8785, JSON Canonicalization Scheme. Defines deterministic JSON serialization, prohibits duplicate object names for JCS input, and preserves Unicode strings without normalization. RFC 8785.
  1. Unicode Standard Annex on normalization. Revision 57 for Unicode 17.0.0, dated July 30, 2025, explains canonical and compatibility normalization, stability and conformance tests. UAX #15.
  1. WebAssembly specifications. The core and JavaScript-interface specifications define memory limits, page sizing, memory growth and buffer behavior. TinyRustLM must still impose smaller application-level limits. WebAssembly core specification and WebAssembly JavaScript interface.
  1. WebGPU specification. Defines validation and device-loss behavior, including asynchronous loss and implementation-defined messages. The retrieved current editor’s draft was updated in July 2026, while a dated January 2026 Candidate Recommendation Draft is also available for pinning. WebGPU specification.
  1. Microsoft Windows filesystem documentation. Primary documentation for reserved names, namespaces, NUL and control restrictions, symbolic links/reparse points and alternate data streams. Naming Files, Paths, and Namespaces, Symbolic Link Programming Considerations, and Alternate Data Streams.
  1. MITRE CWE-22. Authoritative weakness classification and mitigation discussion for path traversal, canonicalization, separator variants and diagnostic leakage. CWE-22.
  1. Safetensors format repository. A useful primary reference for a data-only tensor format with explicit header length, tensor offsets, duplicate-key rejection and full buffer coverage. It is an architectural comparison, not a substitute for a TinyRustLM specification or independent review. Safetensors repository.
  1. PyTorch security guidance and advisory. Current PyTorch documentation warns never to load untrusted data with torch.load; the official 2025 advisory documents an RCE affecting earlier weights_only=True behavior. This supports the rule that model artifacts must remain data-only and that “restricted” deserializers require adversarial testing. PyTorch @@MKREPORTTOKEN2@@ documentation and GHSA-53q9-r3pm-6pq6.
  1. QuickCheck and coverage-guided property testing. Foundational and later primary research describing generated properties, shrinking and the complementary relationship between property-based and coverage-guided testing. QuickCheck publication record and Coverage Guided, Property Based Testing.
  1. Differential testing. McKeeman’s foundational work motivates comparing implementations to expose inconsistencies; TinyRustLM should combine this method with a specification-based adjudication process. Differential Testing for Software.