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).
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:Repro
An XMILE aux with documentation
cost is 5 | maybe 6 ~ per yearexports 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_6with equationTIME) 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)
docandunitsviawrite_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********banner emitted bywrite_equations_section(writer.rs:2874) -- a group name containing the banner/terminator syntax corrupts the sketch/group structure\\\---///sketch-section terminator would end the equations section prematurelyOnly 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-equivalence22: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).