Skip to content

Fix/jpeg metadata marker bounds#5174

Open
ssh4net wants to merge 5 commits intoAcademySoftwareFoundation:mainfrom
ssh4net:fix/jpeg-metadata-marker-bounds
Open

Fix/jpeg metadata marker bounds#5174
ssh4net wants to merge 5 commits intoAcademySoftwareFoundation:mainfrom
ssh4net:fix/jpeg-metadata-marker-bounds

Conversation

@ssh4net
Copy link
Copy Markdown
Contributor

@ssh4net ssh4net commented Apr 30, 2026

Description

Fixes bounds checks for malformed JPEG APP1 Exif and APP2 ICC metadata
markers.

Before this change, APP1 markers were treated as Exif when they started with
"Exif" and had at least 4 bytes. The reader then skipped 6 bytes for the
Exif\0\0 prefix, so short payloads such as Exif or Exif\0 could advance
past the saved marker buffer and underflow the remaining length passed to the
Exif parser.

The APP2 ICC path also used strcmp() on raw marker bytes before proving the
marker was long enough or NUL-terminated. Short APP2 markers could therefore be
read past the saved marker buffer, and the code later accessed sequence bytes
and subtracted ICC_HEADER_SIZE without first checking the marker length.

This is reachable by normal OpenImageIO image-open paths, including tools such
as iinfo, iconvert, and oiiotool, when opening a malformed JPEG.

The fix adds bounded marker-prefix helpers:

  • APP1 Exif is accepted only when the full Exif\0\0 prefix is present.
  • APP2 ICC is accepted only when the marker is at least ICC_HEADER_SIZE bytes
    and matches ICC_PROFILE\0 using bounded comparison.

Tests

Added coverage to testsuite/jpeg-corrupt for short APP1/APP2 metadata
markers:

  • APP1 Exif payload lengths 4 and 5
  • APP2 ICC payload lengths 11, 12, and 13

Validated locally with:

ctest --test-dir build-jpeg-only -R '^jpeg-corrupt$' --output-on-failure

Checklist:

  • I have read the guidelines on contributions and code review procedures.
  • I have read the Policy on AI Coding Assistants
    and if I used AI coding assistants, I have an `Assisted-by: Codex GPT 5.5xHigh
    line in the pull request description above.
  • I have updated the documentation if my PR adds features or changes
    behavior.
  • I am sure that this PR's changes are tested in the testsuite.
  • I have run and passed the testsuite in CI before submitting the
    PR, by pushing the changes to my fork and seeing that the automated CI
    passed there. (Exceptions: If most tests pass and you can't figure out why
    the remaining ones fail, it's ok to submit the PR and ask for help. Or if
    any failures seem entirely unrelated to your change; sometimes things break
    on the GitHub runners.)
  • My code follows the prevailing code style of this project and I
    fixed any problems reported by the clang-format CI test.
  • If I added or modified a public C++ API call, I have also amended the
    corresponding Python bindings. If altering ImageBufAlgo functions, I also
    exposed the new functionality as oiiotool options.

ssh4net and others added 4 commits July 23, 2025 19:13
avcodec_close (AVCodecContext *avctx) removing in ffmpeg 7.2 and was deprecated for couple years

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Comment thread testsuite/jpeg-corrupt/run.py Outdated
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
@ssh4net ssh4net force-pushed the fix/jpeg-metadata-marker-bounds branch from 6a3d866 to 756ee90 Compare April 30, 2026 09:31


def iconvert_to_null(filename, success_marker):
output = filename.rsplit(".", 1)[0] + ".null"
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.

Since null files never get written, there is not a reason to carefully construct the filename based on the input, just always call it "out.null" and be done with it.

I don't think you need the iconvert_to_null function at all. I would modify runtest.py's iconvert() function to take a new optional argument success_message and if it's non-empty, have it append "&& echo" + success_message (much in the way that it appends || true if you set failureok), then for the test you can just say

command += iconvert("foo.jpg out.null", successmessage="foo-ok")

Copy link
Copy Markdown
Collaborator

@lgritz lgritz left a comment

Choose a reason for hiding this comment

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

LGTM.

I made a suggestion for simplifying the test logic that boils down to:

  • 2-line extension to runtest.py's iconvert function.
  • No custom logic in this one test directory's run.py
  • Just use command += iconvert(...) with the new option

Other than that, this is ready to go, thanks for the fix.

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