Skip to content

Treat an MPO with too few MP entries as a JPEG#9826

Merged
radarhere merged 2 commits into
python-pillow:mainfrom
LuShadowX:mpo-entry-count-struct-error
Jul 27, 2026
Merged

Treat an MPO with too few MP entries as a JPEG#9826
radarhere merged 2 commits into
python-pillow:mainfrom
LuShadowX:mpo-entry-count-struct-error

Conversation

@LuShadowX

Copy link
Copy Markdown
Contributor

jpeg_factory() deliberately falls back to a plain JPEG when the MP index cannot be read. It catches TypeError and IndexError, and warns for SyntaxError, which is what test_bad_mpo_header covers. One case in _getmp() escapes that: struct.error.

The MP index stores the number of images (0xB001) and the MP entries (0xB002) separately, and nothing checks that they agree. If the number of images is larger than the number of entries actually present, struct.unpack_from() reads off the end of the entry buffer:

>>> data = open("Tests/images/sugarshack.mpo", "rb").read()
>>> data = data[:6048] + struct.pack(">I", 3) + data[6052:]  # 2 images -> 3
>>> Image.open(BytesIO(data))
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x...>

struct.error is not caught in jpeg_factory(), so it reaches _open_core(), which treats it as "this plugin cannot open the file". JPEG is the only format that accepts the prefix, so the whole image becomes unopenable even though the JPEG data itself is fine.

Removing the MP entry tag instead raises KeyError inside _getmp(), which is already turned into SyntaxError("malformed MP Index (bad MP Entry)"), and that file opens as a JPEG with a warning. A short entry buffer means the same thing, so this raises the same error for it.

Changes proposed in this pull request:

  • Raise SyntaxError instead of letting struct.error escape _getmp() when the MP index declares more images than it has entries
  • Add a test next to test_bad_mpo_header

Comment thread Tests/test_file_jpeg.py Outdated
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
@radarhere
radarhere merged commit 53711df into python-pillow:main Jul 27, 2026
50 checks passed
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