Skip to content

fix: prevent PDF LayoutError, header overlap, and layout issues#1

Open
deacon-mp wants to merge 7 commits intomasterfrom
fix/pdf-large-operation-table-overflow
Open

fix: prevent PDF LayoutError, header overlap, and layout issues#1
deacon-mp wants to merge 7 commits intomasterfrom
fix/pdf-large-operation-table-overflow

Conversation

@deacon-mp
Copy link
Copy Markdown
Owner

Mirror of mitre/debrief PR mitre#79 for Copilot review

…verflow

Large operations with many detection strategies caused LayoutError because
KeepTogether forced header+table onto a single page. KeepTogetherSplitAtTop
allows the table to split across pages when it exceeds the frame height.
This matches the pattern already used by all other debrief report sections.

Also fixes header/footer rendering on landscape pages by using actual page
dimensions (canvas._pagesize) instead of doc.width/doc.height which retain
portrait values regardless of the active PageTemplate orientation.
…op_id bug

- Remove unused imports (MagicMock, patch, inch, PageBreak, Frame, PageTemplate)
  and unused variable (paw_to_platform) from test_pdf_large_table.py
- Fix file handle leak in c_story.py: use context manager for svg.write()
- Add null check for missing viewBox attribute in adjust_icon_svgs()
- Fix stale op_id variable in build_steps_d3() — use operation.id instead
Row-spans on the AN/Platform/Statement columns prevented ReportLab from
splitting large detection tables across pages, causing LayoutError even
with KeepTogetherSplitAtTop. Tables with many analytics rows (e.g., SMB
Lateral Movement with 14+ techniques) would exceed the 564pt landscape
frame height and crash.

The fix:
- Separate the header block from the table (header kept together, table
  flows freely)
- Disable auto-generated row-spans that blocked page splitting
- Enable splitByRow=True and splitInRow=True for robust splitting
…overlap

- Tactics column: wrap tactic names in Paragraph with wordWrap='CJK' and
  widen column from 0.75in to 1.10in so names like "Privilege-escalation"
  don't overflow into adjacent columns
- Detection header/table gap: re-combine header block and table into a
  single KeepTogetherSplitAtTop flowable (the gap was caused by
  Story.append adding 12pt spacer between separate flowables)
- Landscape header overlap: use actual frame margins for header/footer
  positioning instead of doc-level portrait margins. Landscape frames
  use 18pt margins but doc.topMargin was 84pt, causing the
  "OPERATIONS DEBRIEF" title to draw over the table content area
- Tactics column: use .title() for proper capitalization of each word
  (e.g., "Lateral-Movement" not "Lateral-movement") and insert <br/>
  after hyphens so multi-word tactics display on separate lines
- Landscape header: on continuation pages, detect landscape orientation
  and render a compact 8pt header with thin line at page top instead
  of the full 18pt header that was overlapping the table content area
  (landscape frames use 18pt margins vs portrait's 84pt)
The 18pt landscape margins are too narrow to render any header text
without overlapping the detection table content. Landscape continuation
pages now render only the page number footer.
Adds assertion that at least one Table flowable is generated, guarding
against ATT&CK data changes that could reduce the table below the
split threshold and make the regression test vacuous.
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