VIEW THIS AS

Auto mode follows the Route Engine until you choose a viewpoint.

YOU ARE HERE

ROUTE CHECK

CONNECTED TO

WHAT NEXT

Use the canonical route for this room, or HELP if you are unsure.

How Encoding Works | Malformed Input — What a Decoder Should Do With Invalid Byte Sequences

eduKate Secondary students reviewing open books for How Super Intelligence Works: the SI Failure Map.

The decoder reads a byte.

It expects two continuation bytes.

The stream ends after one.

There is no valid character hiding there waiting to be guessed.

Malformed input is the point where a byte sequence violates the grammar of the declared encoding, forcing the decoder to follow an explicit error policy rather than inventing meaning.

This is the fourth pillar beneath How Encoding Works. The master owns the encoding contract. This article owns the contract’s failure state: how decoders distinguish valid sequences from invalid ones and what replacement, rejection and recovery mean for interoperability and security.

Quick Read

UTF-8 has a precise byte grammar. ASCII bytes stand alone. Other leading bytes announce sequences of two, three or four bytes, with constrained continuation ranges that prevent overlong encodings, surrogate values and code points above U+10FFFF. A decoder encountering an invalid sequence must not silently invent an alternative character mapping. The current WHATWG Encoding Standard defines interoperable replacement-mode decoding for ordinary text and fatal-mode decoding for contexts that require failure. Replacement commonly surfaces U+FFFD, the replacement character. Whether to replace or fail is an application boundary: display systems may prioritise continued rendering, while identifiers, signatures, security tokens and strict data formats may need rejection.

declared encoding → byte grammar → valid sequence? → decode scalar value / signal error → replacement or fatal policy → downstream validation

UTF-8 Is a Grammar, Not a Guess

UTF-8 uses one to four bytes per Unicode scalar value.

The first byte tells the decoder how many bytes the sequence requires.

Continuation bytes must fall inside defined ranges.

Additional constraints prevent illegal scalar values.

The decoder therefore has a finite state:

  • how many continuation bytes are needed;
  • how many have been seen;
  • what partial code point has been accumulated;
  • what range the next byte may occupy.

Malformed input is detected when those constraints fail.

ASCII Is the One-Byte Case

UTF-8 bytes 0x00 through 0x7F map directly to the corresponding ASCII/Unicode scalar values.

This backwards-compatible region is one reason UTF-8 became so practical.

It also means ASCII-only test suites can miss almost every multi-byte decoder failure.

A Leading Byte Creates an Obligation

A two-byte leading byte means:

one valid continuation byte must follow.

A three-byte leader requires two.

A four-byte leader requires three.

If end-of-stream arrives early, the sequence is malformed.

A Continuation Byte Cannot Start a Character

UTF-8 continuation bytes occupy a reserved range.

If one appears where a new character must begin, the sequence is invalid under UTF-8.

The byte might be meaningful under another encoding.

That would be a different decoder contract—not permission for the UTF-8 decoder to improvise.

Overlong Encodings Are Invalid

UTF-8 requires each scalar value to use its shortest permitted sequence.

An ASCII character cannot be represented legally using a longer multi-byte sequence.

This canonicality matters for security.

If one component treats an overlong sequence as equivalent to a normal ASCII character while another rejects it, validation and interpretation can disagree.

UTF-16 Surrogate Code Points Are Not UTF-8 Scalar Values

The code-point range U+D800–U+DFFF is reserved for UTF-16 surrogate code units and does not represent Unicode scalar values.

UTF-8 sequences that would decode into this range are invalid.

The current WHATWG UTF-8 decoder explicitly constrains relevant byte ranges to prevent such output.

Values Above U+10FFFF Are Invalid Too

Unicode scalar values stop at U+10FFFF.

Four-byte UTF-8 sequences must respect upper bounds that prevent values beyond the Unicode codespace.

A decoder accepting larger values is not merely “being tolerant.” It is violating the encoding contract.

WHATWG Defines Replacement and Fatal Processing Modes

The current WHATWG Encoding Standard defines UTF-8 decoding hooks for both replacement-style processing and a “decode without BOM or fail” path that returns failure on an error.

This separation is useful because application requirements differ.

Web display may need best-effort text.

A strict identifier parser may need to stop.

Replacement Mode Preserves Stream Progress, Not Original Meaning

When a decoder substitutes U+FFFD for an error, it preserves the fact that decoding failed at that region and allows surrounding valid text to continue.

It does not reconstruct the missing intended character.

U+FFFD means “a decoding problem occurred here,” not “this was the original character.”

Replacement Is Lossy

Several distinct malformed byte sequences may all become the same U+FFFD character.

After replacement, those original byte differences may be unrecoverable unless raw bytes were preserved elsewhere.

Logs and forensic pipelines should understand this before throwing away source data.

Fatal Mode Protects Exactness

Some contexts cannot safely proceed after a decoding error.

  • cryptographic identifiers;
  • protocol control fields;
  • canonical data interchange;
  • security principals;
  • digitally signed content before canonical verification.

In these cases, replacing an invalid sequence may transform “invalid input” into a valid but different string.

Failing closed can preserve the distinction between valid data and repaired display text.

The Error Policy Must Be Shared Across Security Boundaries

A gateway rejects one malformed sequence.

The application repairs it differently.

Or the gateway replaces one region while the application reconsumes a restored byte differently.

Any disagreement between validator and consumer creates an interpretation gap.

The safest architecture decodes once under a standards-defined policy and passes the decoded representation forward rather than repeatedly reinterpreting raw bytes.

Decoder Differentials Have Been Security Bugs

The WHATWG Encoding Standard explicitly discusses security issues arising when producers and consumers interpret invalid multi-byte sequences differently.

An attacker benefits when:

  • filter sees harmless text;
  • consumer sees dangerous text;
  • both believe they handled the same bytes.

Interoperable error handling closes part of that gap.

Do Not Fall Back Silently to Another Charset

Declared UTF-8 contains an invalid sequence.

A tempting response is:

Maybe it was Windows-1252. Try that.

That may be useful as a recovery hypothesis in a forensic tool.

It is dangerous as invisible runtime behaviour because the same input can receive different meanings depending on environment or guess order.

Mojibake Is a Different Problem

The third pillar, Mojibake, covers text decoded under the wrong character mapping.

Malformed Input covers bytes that are invalid under the chosen mapping.

Recovery tools may consider another charset.

A strict decoder should not silently change contracts mid-stream.

Truncated Network Messages Need Framing Before Decoding

A multi-byte sequence is split across two network chunks.

The first chunk ends after the lead byte.

That is not necessarily malformed if the decoder is operating in streaming mode and knows more bytes may arrive.

Only end-of-stream with an unfinished sequence is an error.

Streaming decoders need state.

Chunk Boundaries Are Not Character Boundaries

A transport layer can split bytes anywhere.

UTF-8 code-point sequences can cross transport chunks.

Grapheme clusters can cross code-point boundaries after decoding.

The first pillar, Grapheme Clusters, owns the later user-perceived segmentation layer.

Streaming APIs Need Flush Semantics

While more input may arrive, an incomplete sequence can remain buffered.

When the stream is explicitly closed or flushed, unfinished state must be resolved according to the error policy.

“No bytes right now” and “there will never be more bytes” are different states.

Replacement Placement Must Be Deterministic

Even if two decoders both use U+FFFD, they can still disagree on how many replacement characters to emit for one malformed byte region.

That difference changes the resulting Unicode string.

The WHATWG UTF-8 decoder defines concrete state transitions so implementations converge on the same output rather than choosing ad hoc recovery spans.

U+FFFD in Source Text Is Not Always a Decoder Error

The replacement character itself is a valid Unicode scalar value.

A document can intentionally contain U+FFFD.

Therefore seeing � on screen is evidence consistent with a past decoding failure, not absolute proof of when or where the failure occurred.

Preserve Raw Bytes When Forensics Matter

A decoder emits U+FFFD.

If the application stores only the resulting Unicode text, exact malformed source bytes may be lost.

For logging, evidence preservation, migration and debugging, a safe design can retain:

  • raw bytes or hash/attachment where permitted;
  • declared charset;
  • decoder version/policy;
  • error offsets;
  • decoded text;
  • whether replacement occurred.

Error Offsets Need a Named Unit

“Error at position 15.”

Position in what?

  • byte offset;
  • code-unit offset;
  • code-point index;
  • grapheme index.

Decoder errors originate in the byte stream, so byte offsets are often the most diagnostic representation.

Normalization Must Wait Until Decoding Produces Unicode Text

The second pillar, Unicode Normalization, operates on Unicode code-point sequences.

It should not be used as a byte-validation mechanism.

The pipeline order matters:

validate/decode bytes → Unicode text → normalize if policy requires

Replacement Can Create Downstream Collisions

Two distinct invalid byte sequences both become U+FFFD.

A later comparison sees the same Unicode string.

Distinct source evidence has collapsed.

This is why replacement-decoded text should not automatically be used as a cryptographic identity or authoritative source record.

Search Can Index Replacement Damage Faithfully

Decoder replaces invalid bytes.

Indexer tokenizes the resulting text perfectly.

The search layer is functioning correctly on already-damaged representation.

Downstream correctness cannot repair upstream loss automatically.

APIs Should Distinguish “Invalid Input” From “Valid Text Containing U+FFFD”

If an API accepts decoded strings only, the decoder error state may already have disappeared.

Where fidelity matters, pass validation metadata or reject malformed byte input before the string enters the semantic layer.

User-Facing Systems Sometimes Need Tolerant Display

A browser opening an old imperfect page should usually show as much readable text as possible rather than crash the entire document.

Replacement-style decoding supports graceful degradation.

This does not imply the repaired text is suitable as authoritative input to every downstream system.

Machine Interfaces Often Need Stricter Failure

A signed JSON-like protocol field.

An account identifier.

A policy selector.

If malformed bytes are replaced silently, the decoder may create a valid string that no sender intentionally signed or named.

Failing is safer when exact representation is part of authority.

Test Suites Must Include Malformed Sequences Deliberately

Do not test only valid multilingual text.

Include:

  • lone continuation bytes;
  • truncated multi-byte sequences;
  • overlong forms;
  • surrogate-targeting sequences;
  • values beyond U+10FFFF;
  • invalid continuation ranges;
  • malformed sequences adjacent to valid ASCII;
  • stream boundaries inside valid sequences.

The decoder’s error boundary deserves tests as much as its happy path.

Differential Testing Is Powerful

Feed the same malformed byte cases into several supposedly standards-compatible decoders.

If outputs differ, investigate whether:

  • one library follows another standard;
  • one uses a legacy compatibility mode;
  • one is buggy;
  • your invocation selected different error policies.

Interoperability bugs often hide in error paths because ordinary valid text never exercises them.

Decoder Version Is Part of Reproducibility

Unicode and web encoding standards are versioned or living specifications.

The basic UTF-8 grammar is stable, but implementation and surrounding API behaviour can evolve.

High-stakes pipelines should record library/runtime versions when exact reproduction matters.

A Better Malformed-Input Model

raw bytes + declared encoding → standards-defined decoder state → valid scalar or error → explicit replacement/fatal policy → error metadata → downstream normalization/segmentation only after successful decoding semantics are known

A 30-Lens Malformed Input Audit

  1. Encoding: which byte grammar is declared?
  2. Bytes: are raw bytes available?
  3. Leader: does the first byte start a valid sequence?
  4. Continuation: are required continuation bytes valid?
  5. Truncation: did the stream end mid-sequence?
  6. Overlong: is a value encoded using too many bytes?
  7. Surrogate: would the sequence decode into U+D800–U+DFFF?
  8. Upper bound: would it exceed U+10FFFF?
  9. Streaming: is temporary incompleteness being confused with final truncation?
  10. Flush: when is end-of-stream declared?
  11. Error policy: replacement or fatal?
  12. Replacement: is U+FFFD emitted?
  13. Replacement span: how many errors are emitted for the malformed region?
  14. Determinism: do all components decode identically?
  15. Fallback: is another charset tried silently?
  16. Mojibake: is this actually wrong mapping rather than invalid grammar?
  17. Byte offset: where did decoding fail?
  18. Raw preservation: can the malformed source be recovered?
  19. Logging: is replacement recorded?
  20. Security filter: did it use the same decoder as consumer?
  21. Identifier: can replacement create a valid but unintended name?
  22. Signature: are exact bytes authoritative?
  23. Normalization: does it occur only after decoding?
  24. Indexing: could search faithfully index repaired text as if original?
  25. API: does downstream code know a decode error occurred?
  26. UX: should display continue around errors?
  27. Machine protocol: should malformed input fail closed?
  28. Tests: are hostile malformed sequences covered?
  29. Version: what decoder/runtime implemented the policy?
  30. Return: can the system reproduce the exact decode decision from bytes and metadata?

Laboratory 1: Truncate a Multi-Byte Character

Take a valid multi-byte UTF-8 sequence and remove its final continuation byte. Compare a replacement-mode decoder with a fatal-mode decoder. What information does each preserve?

Laboratory 2: Filter and Consumer

Design a fictional security filter and application that use different malformed-input policies. Show how the same bytes can produce an interpretation gap, then repair the architecture by decoding once.

Laboratory 3: Replacement Is Loss

Create two different invalid byte sequences that both become U+FFFD under replacement. After storing only the decoded string, ask whether the original byte source can still be uniquely recovered.

For Primary Readers

Imagine a code where a red card promises two blue cards afterward. If only one blue card arrives before the message ends, the code is incomplete. A decoder should say “there is an error,” not invent the missing card.

For Secondary Readers

Explain why a UTF-8 decoder needs state and why an unfinished sequence at final end-of-stream differs from a valid sequence temporarily split across network chunks.

For Advanced Readers

Model decoding as a deterministic state machine over bytes with explicit error transitions. Security depends on validator and consumer sharing the same transition semantics; replacement is a lossy projection from malformed byte histories into valid Unicode text, while fatal decoding preserves invalidity as a control state.

Common Misconceptions

  • “Any strange text means invalid UTF-8.” Mojibake can arise from valid bytes decoded under the wrong charset.
  • “U+FFFD is the original unknown character.” It marks replacement after decoding error; the original bytes may represent several possibilities or no valid character under that encoding.
  • “A tolerant decoder is always safer.” Display tolerance and security-sensitive identity have different needs.
  • “An incomplete sequence at the end of a network chunk is malformed.” Streaming decoders can buffer it until more bytes arrive; only final unresolved truncation is an error.
  • “If two decoders both replace errors, they are equivalent.” Replacement placement and recovery spans must also agree.

Research Corridor

Frequently Asked Questions

What makes UTF-8 input malformed?

A sequence is malformed when its bytes violate UTF-8’s permitted leading-byte, continuation-byte, scalar-value or sequence-length constraints.

What is U+FFFD?

U+FFFD is the Unicode replacement character, commonly emitted when a decoder in replacement mode encounters invalid input. It marks decoding failure rather than recovering the original intended character.

When should malformed input cause a fatal error?

When exact representation is required for identity, security, signatures, protocol control or other cases where silently replacing invalid bytes could create a different valid meaning.

Final Thought: Failure Is Part of the Encoding Contract

A standard does not become interoperable merely by defining how valid data succeeds.

Real interoperability begins when every receiver knows what the same bad byte sequence is allowed to mean—and when it must mean nothing at all.

ENCODING · FOUR PILLAR LEGS

Return to How Encoding Works, or continue through Grapheme Clusters, Unicode Normalization and Mojibake. Return to the Information & Representation Hub.

Discover more from eduKate Singapore

Subscribe now to keep reading and get access to the full archive.

Continue reading