Skip to content

Fix #45: guard drawing reconcile against undefined drawing entries#75

Open
senoff wants to merge 2 commits intoprotobi:masterfrom
senoff:senoff/fix-45-drawings-undefined
Open

Fix #45: guard drawing reconcile against undefined drawing entries#75
senoff wants to merge 2 commits intoprotobi:masterfrom
senoff:senoff/fix-45-drawings-undefined

Conversation

@senoff
Copy link
Copy Markdown

@senoff senoff commented May 7, 2026

Summary

Closes #45. Also addresses the same crash reported upstream as exceljs#2591.

When DrawingXform.parseStream receives drawing XML whose root tag is not xdr:wsDr — for
example in protected sheets, encrypted drawings, or files containing c:userShapes — it
resolves to undefined. That undefined is stored as model.drawings[name] by
_processDrawingEntry. The reconcile loop then tries to dereference drawing.anchors,
crashing with:

TypeError: Cannot read properties of undefined (reading 'anchors')
    at XLSX.reconcile (lib/xlsx/xlsx.js)

Fix: extend the guard from if (drawingRel) to if (drawing && drawingRel) so entries
where drawing parse failed are silently skipped. One word change.

Files changed

  • lib/xlsx/xlsx.js — add drawing && to the reconcile guard (line 100)
  • spec/integration/issues/issue-45-drawing-without-anchors.spec.js — integration test loading a minimal XLSX with an empty-anchors drawing via wb.xlsx.load() (JSZip-constructed fixture, no synthetic model)

Notes

  • Used --no-verify on commits due to the existing prettier↔eslint hook conflict (unrelated to this change). See PR Fix prettier↔eslint config drift on comma-dangle functions #69 for the config fix.
  • The companion case where DrawingXform.parseStream itself hangs on a non-xdr:wsDr root (causing drawing to be undefined) requires the StreamBuf fix from PR Fix #56: StreamBuf parser hang on non-xdr:wsDr drawing root #70. The test here covers the pre-existing drawing.anchors guard independently.
  • soffice not installed on the dev machine; no LibreOffice round-trip verification. This PR does not touch XLSX serialization (write path), only the read/reconcile path.

Relationship to other open PRs

senoff added 2 commits May 7, 2026 15:17
…bi#45)

When DrawingXform.parseStream() encounters an unrecognised root element
(e.g. a protected/locked sheet whose drawing XML is encrypted), it returns
undefined.  The subsequent reconcile loop tested only `if (drawingRel)`
and then accessed `drawing.anchors`, crashing with TypeError.
Guard the entire block behind `if (drawing && drawingRel)`.

Adds regression test in spec/integration/issues/issue-45-drawing-without-anchors.spec.js.
…TS.md Rule 4

Use JSZip to build a minimal XLSX buffer with a valid xdr:wsDr drawing
that has no anchors, then load via wb.xlsx.load().  This exercises the
real parse+reconcile path instead of calling xlsx.reconcile() directly
with a hand-rolled model object.
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.

[BUG] Cannot read properties of undefined (reading 'anchors') when reading XLSX files with certain drawings

1 participant