Skip to content

Fix OOXML schema validity, correctness, perf, and security issues#30

Merged
SimonCropp merged 1 commit into
mainfrom
Fix-OOXML-schema-validity,-correctness,-perf,-and-security-issues
Jun 26, 2026
Merged

Fix OOXML schema validity, correctness, perf, and security issues#30
SimonCropp merged 1 commit into
mainfrom
Fix-OOXML-schema-validity,-correctness,-perf,-and-security-issues

Conversation

@SimonCropp

Copy link
Copy Markdown
Member

Correctness:

  • Tables: derive column count from the rowspan grid so cells in later, wider rows are no longer silently dropped
  • Tables: thread FootnoteIndex/BookmarkId through per-cell contexts and seed FootnoteIndex from the existing part, so footnote and bookmark IDs no longer collide across cells or across Build calls
  • Emit w:rPr and w:tcPr children in OOXML schema order; previously the output was schema-invalid and only tolerated by Word
  • Cell margins emit w:left/w:right instead of the invalid w:start/w:end
  • ColorParser: accept percentage and decimal rgb()/rgba() components
  • vertical-align is matched case-insensitively
  • word-spacing no longer doubles letter-spacing
  • @page: match the closing brace and skip nested margin-box rules so sibling declarations (margin/size) are not lost

Performance:

  • Parse each element's inline style once instead of twice
  • Allocate list numbering IDs from the threaded NextNumId counter rather than rescanning the numbering part per list (O(m^2) -> O(m))
  • Compute ordered-list item indices in a single pass (O(n^2) -> O(n))

Security:

  • Image fetch: disable auto-redirect and re-check each redirect hop against the image policy (closes a SafeDomains/SSRF bypass), cap the response size, set a timeout, and parse width/height with InvariantCulture

Tests:

  • Add rowspan, footnote-id, bookmark-id, and OpenXmlValidator round-trip tests, plus rgb() percentage cases
  • Regenerate affected verified baselines (structural reordering only; rendered text/image output unchanged)

Correctness:
- Tables: derive column count from the rowspan grid so cells in later,
  wider rows are no longer silently dropped
- Tables: thread FootnoteIndex/BookmarkId through per-cell contexts and
  seed FootnoteIndex from the existing part, so footnote and bookmark IDs
  no longer collide across cells or across Build calls
- Emit w:rPr and w:tcPr children in OOXML schema order; previously the
  output was schema-invalid and only tolerated by Word
- Cell margins emit w:left/w:right instead of the invalid w:start/w:end
- ColorParser: accept percentage and decimal rgb()/rgba() components
- vertical-align is matched case-insensitively
- word-spacing no longer doubles letter-spacing
- @page: match the closing brace and skip nested margin-box rules so
  sibling declarations (margin/size) are not lost

Performance:
- Parse each element's inline style once instead of twice
- Allocate list numbering IDs from the threaded NextNumId counter rather
  than rescanning the numbering part per list (O(m^2) -> O(m))
- Compute ordered-list item indices in a single pass (O(n^2) -> O(n))

Security:
- Image fetch: disable auto-redirect and re-check each redirect hop
  against the image policy (closes a SafeDomains/SSRF bypass), cap the
  response size, set a timeout, and parse width/height with
  InvariantCulture

Tests:
- Add rowspan, footnote-id, bookmark-id, and OpenXmlValidator round-trip
  tests, plus rgb() percentage cases
- Regenerate affected verified baselines (structural reordering only;
  rendered text/image output unchanged)
@SimonCropp SimonCropp merged commit 3b790fb into main Jun 26, 2026
2 of 3 checks passed
@SimonCropp SimonCropp deleted the Fix-OOXML-schema-validity,-correctness,-perf,-and-security-issues branch June 26, 2026 03:11
@SimonCropp SimonCropp added this to the 1.0.4 milestone Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant