Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions docs/SAFETY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@ For each file EC is allowed to convert:
8. Atomically installs the verified temporary output where the platform supports it.
9. Marks the recovery record `Completed` after installation succeeds.

If a required step fails, EC does not install converted output. Because the
backup is created before decoding and encoding, a later conversion failure can
leave a valid `.bak` beside an unchanged source; metadata is not written until
both the output and backup have verified.
If a step before installation (step 8) fails, EC does not install converted
output and the source is unchanged. Because the backup is created before decoding
and encoding, a later conversion failure can leave a valid `.bak` beside an
unchanged source; metadata is not written until both the output and backup have
verified.

If step 9 fails, installation has already happened: the verified converted output
is in place, EC reports a recovery-record error with the replacement recorded as
committed, and the `Prepared` record keeps the hashes needed to inspect the result.
Do not treat that file as unchanged.

## Source-encoding policy

Expand Down Expand Up @@ -53,6 +59,9 @@ This is intentionally conservative: most ordinary BOM-less UTF-16 files are
expected to be refused. It costs a second full read, which is deliberate because
rewriting a file must not rest on a sample-based byte-order guess.

Choose `-From utf-16le` or `-From utf-16be` if you know the source order. That
chooses the source interpretation only; it does not bypass any other safeguard.

### BOM-less UTF-32

EC never converts it automatically. It reports `Refused` with reason code
Expand All @@ -67,8 +76,10 @@ pass it through. Separately, genuine UTF-32 can be valid under both orders.
The cost is that ordinary BOM-less UTF-32 is refused too. Nothing in the bytes
separates it from the UTF-16 file above. Add a BOM, or name the source.

Choose `-From utf-16le` or `-From utf-16be` if you know the source order. That
Choose `-From utf-32le` or `-From utf-32be` if you know the source order. That
chooses the source interpretation only; it does not bypass any other safeguard.
Naming a UTF-16 order for a UTF-32 file would read its bytes as UTF-16, so use
only the UTF-32 names.

## Plans, backups, and recovery metadata

Expand Down
9 changes: 4 additions & 5 deletions sources/EncodingChecker/ConversionMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,12 @@ internal sealed record ConversionMetadata
public required bool SourceHasBom { get; init; }

/// <summary>
/// What detection concluded, or <see langword="null"/> when detection did not run.
/// What detection concluded, or <see langword="null"/> when it identified no codec.
/// </summary>
/// <remarks>
/// This is null only when detection did not run, such as a CLI <c>-From</c>
/// conversion. A GUI user can explicitly choose a source after a scan; in that
/// case the sidecar preserves both the detector's earlier conclusion and the
/// codec the conversion actually used.
/// Detection runs even when the source is chosen explicitly, such as with a CLI
/// <c>-From</c> or a GUI choice after a scan, so the sidecar preserves the detector's
/// conclusion beside the codec the conversion actually used.
/// </remarks>
[JsonPropertyOrder(15)]
public int? DetectedEncodingId { get; init; }
Expand Down
3 changes: 2 additions & 1 deletion sources/EncodingChecker/ConversionPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ internal static PlannedAction Decide(
return PlannedAction.Skip;
}

// An unchanged file is not read or rewritten, so no source choice is needed.
// An unchanged file is not rewritten, so no source choice is needed. It is still
// read and validated in full after this decision.
//
// Codec identity is the code page, not the label. "utf-16", "unicode", "ucs-2"
// and "utf-16le" all name code page 1200, so comparing the strings reported a
Expand Down
Loading