Found while testing crates/textimport/src/rtf.rs:43-63 (SKIP list) and :201 (`SKIP.contains(&word.as_str())`)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/docx.rs:132-133 (parse, Event::GeneralRef branch)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/export.rs:18 (plain_char) and :177 (rtf)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/tagged.rs:~190-205 (the ParaStyle and CharStyle branches of import: `unescape_value(value.trim())`)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/tagged.rs:~190 (the `n.starts_with("0x")` branch of import: `u32::from_str_radix(&n[2..], 16)`)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/lib.rs:140 (plain) and crates/engine/src/cmd/place_text.rs:372 (place_text)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A footnote reference clones its note and walks it again, and an XLSX shared
string is copied per cell that uses it, so one 1 MB footnote referenced 100k
times meant around 100 GB. The text is kept at the first reference; later ones
get the mark and an empty note, and the report says so. The spreadsheet reader
stops at 64 MB of text and 400,000 collected cells.
Carries both review fixes:
- a footnote id is recorded only once its text has actually been kept, so a
first reference arriving after the budget was spent no longer counts as
"done" and tell the next reference the text is at a reference that has none;
- the report and the note budget are both bounded. The duplicate warning names
the id, so 400 ids referenced twice made 400 warnings, each pushed after a
Vec::contains scan of all the earlier ones; warnings go through warn() now,
which dedups through a set and stops at 100 distinct messages. And the budget
counted only `text`, which holds a table's anchor and not its cells, so 18
notes of 600 KB of cell text retained 10,800,072 bytes against the 8 MB
budget; note_bytes() walks the tables and their nested tables.
Rebased onto the post-split main: the implementation stays in docx.rs and the
tests moved to docx/tests.rs, so the test additions went there.
Found while testing crates/textimport/src/rtf.rs:~118-131 (the \' branch of import: `i += 4` and `u8::from_str_radix(&hex, 16)`)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/tagged.rs:~93-100 (tagged_text, the `<cFont:{v}>` and `<cTypeface:{v}>` writes)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/docx.rs:~272 (the "tbl" branch of Ctx::blocks: `st.insert_table(len, t); first = false;`)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The importers each had their own spelling of "is this a number we can use", or
only checked that it was finite. Measured before the change:
<cSize:1e300> -> Some(1e300) pt tagged text
<cSize:-5> -> Some(-5.0) pt
<cSize:0> -> Some(0.0) pt
w:spacing before=1e300 -> 5e298 pt indent DOCX
DC-12 asks for a shared clamp helper used by every importer, so there are two
in `doc::attrs`, beside the tab limits:
* `imported_type_size` drops a size the engine cannot mean, so the text keeps
the size its style gives it -- which is what RTF and DOCX already did.
* `imported_measure` clamps an indent, spacing or offset to the widest page.
Clamped rather than dropped on purpose: a file that says "indent everything"
still indents as far as the engine goes, where dropping would quietly restore
the style's own indent and hide what the file asked for.
Both are now used by tagged text, DOCX runs and paragraphs, DOCX numbering
levels and RTF -- the last two had the 0.1-1296 pt range as a literal, which is
the duplication that let tagged text drift.
Control: with the helpers back to a finite-only test, both new tests fail, the
DOCX one printing the 5e298 pt spacing in full.
Stale in the issue: its first location, `docx.rs` `w:sz`, is already clamped --
that came with #1574. DC-12's remaining holes are the ones fixed here.
Found while testing crates/textimport/src/rtf.rs:197-243 (the \u handler at :235-242; control words never decrement `pending`)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/docx.rs:134-135
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/docx.rs:183-185
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/docx.rs:183 (run_attrs, w:sz) and :206-214 (para_attrs, w:spacing/w:ind via the `tw` closure)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/tagged.rs:173
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Found while testing crates/textimport/src/xlsx.rs:62 and :112 (shared strings are read with El::text, which includes <rPh> children; inline strings use the same call, crates/textimport/src/docx.rs:37)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
crates/engine/src/dtd.rs: keep the branch's version; #319 already bounds DTD group nesting (with the same limit of 64) along with the entity budget and matching fixes, so this PR's DTD part is dropped. The XML element limits are taken.
crates/textimport/src/docx.rs: keep the branch's page_break_ends_its_paragraph test (already present further down); add the PR's inline content control test.