Skip to content

Return the skipped byte count from the JPEG 2000 decoder skip callback - #10500

Open
professor-moody wants to merge 3 commits into
python-pillow:mainfrom
professor-moody:fix-jpeg2k-skip-return-value
Open

professor-moody wants to merge 3 commits into
python-pillow:mainfrom
professor-moody:fix-jpeg2k-skip-return-value

Conversation

@professor-moody

@professor-moody professor-moody commented Nov 13, 2026 •

Copy link
Copy Markdown

Return the skipped byte count from the JPEG 2000 decoder skip callback

Changes proposed in this pull request:

The JPEG 2000 decoder returned the absolute stream position from its skip callback. OpenJPEG expects the number of bytes skipped, so valid images containing a large XML box could fail to load. j2k_skip now returns p_nb_bytes after a successful relative seek and returns (OPJ_OFF_T)-1 if the seek fails.

The existing PR already includes Python exception propagation and regression coverage for both a successful large skip and a refused relative seek. This update leaves those maintainer-reviewed changes untouched.

This update removes the redundant PyErr_Occurred() pre-checks from j2k_read and j2k_skip. OpenJPEG marks the stream at end and returns immediately after either callback returns -1.

Validated with OpenJPEG 2.5.4 using the JPEG 2000 test module and an instrumented coverage build.

AI assistance was used in drafting and validating this change; the patch and tests were reviewed and verified by the author.

@radarhere

Copy link
Copy Markdown
Member

You will notice that your change is causing Valgrind to fail.

@professor-moody
professor-moody force-pushed the fix-jpeg2k-skip-return-value branch from 697d45c to d67ee82 Compare November 13, 2026 13:22
@radarhere

Copy link
Copy Markdown
Member

Both j2k_read and j2k_skip check PyErr_Occurred() before calling back into Python

Can you explain why you did this? The tests don't demonstrate a need for it. I wouldn't expect OpenJPEG to repeatedly call j2k_read or j2k_skip after an error occurred on our side, I would expect them to abort once we returned (OPJ_OFF_T)-1.

Let OpenJPEG handle the error results already returned by the read and
skip callbacks. Keep the checked seek and skipped-byte-count return.
@professor-moody

Copy link
Copy Markdown
Author

Thanks for pointing this out. The pre-checks were intended to avoid another callback into Python while an exception was pending, but they are redundant with the stream error handling in OpenJPEG 2.5.4. Commit e3a53ef removes both PyErr_Occurred() pre-checks on top of your changes, while keeping the seek error check and the byte-count return.

The recorded CI results for that commit are successful, including Valgrind and codecov/patch. Thanks for the review and the test simplification.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants