Skip to content

engine: MDL writer emits doc/units/group free-text unsanitized, silently corrupting exported models #849

Description

@bpowers

Description

The MDL writer emits variable documentation, units strings, group names/docs, and unit-equivalence settings lines verbatim, with no sanitization or error when the content contains MDL structural characters. write_units_and_comment (src/simlin-engine/src/mdl/writer.rs:1354) writes the units and doc raw between the ~ separators and the | entry terminator:

fn write_units_and_comment(buf: &mut String, units: &Option<String>, doc: &str) {
    buf.push_str("\n\t~\t");
    if let Some(u) = units {
        buf.push_str(u);
    }
    buf.push_str("\n\t~\t");
    buf.push_str(doc);
    buf.push_str("\n\t|");
}

Repro

An XMILE aux with documentation cost is 5 | maybe 6 ~ per year exports to MDL without error. Re-parsing the exported file yields 4 variables instead of 2: the embedded | terminates the equation entry early, and phantom variables (dmnl, maybe_6 with equation TIME) are invented from the trailing text. No error is raised at export or import time -- the model is silently corrupted.

Affected free-text sinks (all unsanitized)

  • Variable doc and units via write_units_and_comment (writer.rs:1354; called from ~6 sites including the settings-section unit entries at line 1598) -- content containing | or ~ breaks entry framing
  • Group names/docs in the ******** banner emitted by write_equations_section (writer.rs:2874) -- a group name containing the banner/terminator syntax corrupts the sketch/group structure
  • Unit-equivalence "22:" settings lines (writer.rs:3233) -- a unit alias containing a comma splits into extra equivalences
  • A doc containing the literal \\\---/// sketch-section terminator would end the equations section prematurely

Only view titles are sanitized today (sanitize_view_title_for_mdl, writer.rs:1968). Identifier quoting was fixed separately (#330/#335), but that covers variable names only, not these free-text fields.

Why it matters

Severity: critical -- silent model corruption on export. A user exporting to Vensim gets a structurally different model (phantom variables, truncated docs, invented equations) with no diagnostic anywhere in the pipeline. This violates the writer's basic contract that the exported file re-parses to an equivalent model, and it is data-dependent: models authored in XMILE (where | and ~ are legal in docs/units) are the trigger.

Components affected

  • src/simlin-engine/src/mdl/writer.rs -- write_units_and_comment, write_equations_section (group banners), the settings-section writers (unit-equivalence 22: lines, unit entries)

Possible approach

A single sanitize-or-error choke point for all free-text fields written into MDL structural positions, analogous to sanitize_view_title_for_mdl: either escape/strip the structural characters (~, |, the \\\---/// terminator, commas in settings lists) with a documented lossy transformation, or reject the export with a clear error naming the offending variable/field. Every free-text emission site should route through it. Round-trip tests should include docs/units containing each structural character.

Context

Discovered during review of the MDL writer's handling of free-text fields; repro verified by exporting an XMILE model with |/~ in an aux doc and re-parsing the output (2 variables became 4, no error raised).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions