Skip to content

ROB: Do not crash on a non-array destination - #3976

Merged
stefan6419846 merged 6 commits into
py-pdf:mainfrom
eeshsaxena:build-destination-non-array
Aug 26, 2026
Merged

stefan6419846 merged 6 commits into
py-pdf:mainfrom
eeshsaxena:build-destination-non-array

Conversation

@eeshsaxena

Copy link
Copy Markdown
Contributor

_build_destination already degrades a null, string, short-array or missing destination to a null destination, but a destination that is some other single object slips past that check and hits page, typ, *array = array, raising TypeError: cannot unpack non-iterable ... object. I hit this reading a PDF whose /Names destination tree had a bare number where a destination array was expected, which crashes reader.named_destinations. Tightened the guard to require an array of at least two elements so anything else falls back the same way the other invalid cases already do.

@codecov

codecov Bot commented Aug 17, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.00%. Comparing base (29f389c) to head (bbfbf0a).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3976   +/-   ##
=======================================
  Coverage   98.00%   98.00%           
=======================================
  Files          57       57           
  Lines       11120    11128    +8     
  Branches     2084     2087    +3     
=======================================
+ Hits        10898    10906    +8     
  Misses        124      124           
  Partials       98       98           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@eeshsaxena

Copy link
Copy Markdown
Contributor Author

Hi! Gentle nudge on this one whenever you have some bandwidth. It's a small, self-contained fix (ROB: Do not crash on a non-array destination), and it's currently mergeable with no conflicts. No urgency at all, and I'm happy to make any changes you'd like. Thanks for maintaining pypdf!

@stefan6419846 stefan6419846 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see the inline remark for some possible changes.

Gentle nudge on this one whenever you have some bandwidth. It's a small, self-contained fix [...] and it's currently mergeable with no conflicts. No urgency at all, and I'm happy to make any changes you'd like.

Please note that the first part of the message does not sound like there is no urgency. Unless there really has been merge activity, but I missed your changes for some time, you can gently ping us. Otherwise, like after less than a day in this case, this just moves your PR down the queue.

Comment thread tests/test_doc_common.py Outdated
@eeshsaxena

Copy link
Copy Markdown
Contributor Author

Fair point on the ping, apologies for that. I'll address the inline remark and push the change, no rush needed on your side.

@stefan6419846 stefan6419846 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review the code style issues.

@eeshsaxena

Copy link
Copy Markdown
Contributor Author

Good catch, that was ruff D209 on the two new test docstrings. Moved the closing quotes to their own line and the code style check passes now. Happy to fold those inline comments into the docstrings too if you'd prefer that.

Comment thread pypdf/_doc_common.py Outdated
Comment thread pypdf/_doc_common.py Outdated
@eeshsaxena

Copy link
Copy Markdown
Contributor Author

Thanks, addressed all three:

  • Switched the check to isinstance(array, ArrayObject) instead of list. That matches how the rest of _doc_common.py types destination arrays (e.g. the isinstance(dest, ArrayObject) right above the call site), and let me drop the long inline union type hint along with the now-unused NumberObject import.
  • Shortened the guard comment.
  • Moved the short_array test note out of inline comments and into a trimmed docstring.

ruff check is clean, mypy is happy with the narrower type, and the build_destination / named_destinations tests pass locally.

@stefan6419846 stefan6419846 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mypy is reporting an issue. Could you please review it?

eeshsaxena and others added 6 commits August 26, 2026 21:26
Addresses the review note on test_doc_common.py: the two new tests now
carry their explanation as a brief docstring rather than a longer inline
comment.
Move the closing docstring quotes onto their own line so the code style
check passes.
…docstring

- Check isinstance(array, ArrayObject) instead of list, matching how the rest
  of _doc_common.py types destination arrays (drops the now-unused NumberObject
  import and the long inline union type hint).
- Shorten the guard comment.
- Move the short_array test's inline comments into a trimmed docstring.
After rebasing on main, #3988 types the destination tree so Fit(fit_args=array)
type-checks without the ignore, and mypy --strict flags it as unused.
@eeshsaxena
eeshsaxena force-pushed the build-destination-non-array branch from f1c7260 to bbfbf0a Compare August 26, 2026 15:57
@eeshsaxena

Copy link
Copy Markdown
Contributor Author

Fixed. After rebasing on main, #3988 now types the destination tree, so Fit(fit_args=array) type-checks on its own and the # type: ignore[arg-type] was flagged as unused. Removed it. mypy . and ruff are clean and the destination tests pass.

And fair point on the earlier nudge, that was a bad habit on my part and the "no urgency" line did read as contradictory. I will leave it with you and not bump it.

@stefan6419846
stefan6419846 merged commit ecabd30 into py-pdf:main Aug 26, 2026
20 checks passed
stefan6419846 added a commit that referenced this pull request Sep 4, 2026
## What's new

### Security (SEC)
- Limit value for Roman numerals (#4047) by @stefan6419846

### New Features (ENH)
- _cmap.py: Also parse encoding for embedded CFF Type1 fonts (#4032) by @PJBrs

### Performance Improvements (PI)
- Cache repeated text extraction character lookups (#4036) by @petermik68-sudo

### Bug Fixes (BUG)
- Treat an empty /Filter array as no filter when extracting images (#4026) by @Anai-Guo
- Detect a duplicate dictionary key whose first value is falsy (#4024) by @devYRPauli
- Make is_open=False collapse outline items (#3998) by @SomSamantray

### Robustness (ROB)
- Multiple changes for wrong inputs by @RavSinghChandan
- Skip trailing duplicate %%EOF markers when locating startxref (#4015) by @Anai-Guo
- Do not crash on a non-array destination (#3976) by @eeshsaxena
- Handle annotations without subtype during merge (#3999) by @Nexlu1

### Documentation (DOC)
- Use AnnotationFlag enum instead of plain integers (#3997) by @RavSinghChandan

### Code Style (STY)
- Multiple small changes detected from test runs by @RavSinghChandan

[Full Changelog](6.16.2...6.17.0)
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.

2 participants