Skip to content

TGA-to-GIF palette split signed overflow causes SIGSEGV

Moderate
lgritz published GHSA-9mwc-fjgj-8wmq Aug 1, 2026

Package

OpenImageIO

Affected versions

v3.1.15.0, v3.0.20.0

Patched versions

>= 3.0.21.0, >= 3.1.16.0

Description

TGA-to-GIF palette split signed overflow causes SIGSEGV

Summary

A tiny truncated TGA can crash OpenImageIO when it is converted to GIF. The PoC declares a 1472 x 12000 RGB TGA image but contains no pixel payload. iinfo -v accepts the image metadata, then oiiotool poc.tga -o out.gif reports the TGA read error and still flushes the pending GIF frame during output close.

The crash reproduces on current main and v3.1.15.0 non-sanitized product binaries as SIGSEGV (rc=139). Sanitizers show the root cause is a signed integer overflow in the GIF palette splitter, followed by a read SEGV.

Impact

An attacker-controlled image can crash applications that use OpenImageIO to transcode this malformed TGA to GIF. Confirmed impact is reliable denial of service with sanitizer-confirmed memory-safety behavior: signed integer overflow and out-of-bounds read.

Precondition: the vulnerable path is reached when writing GIF output. Metadata-only iinfo -v poc.tga does not crash.

Reproduction

bash reproduce.sh

Expected original-binary result:

v3_orig_gif_nolimit     rc=139  SIGSEGV
v3_orig_gif_vm2g        rc=139  SIGSEGV
main_orig_gif_nolimit   rc=139  SIGSEGV
main_orig_gif_vm2g      rc=139  SIGSEGV
v3_orig_iinfo           rc=0    OK, 1472 x 12000 TGA metadata
main_orig_iinfo         rc=0    OK, 1472 x 12000 TGA metadata

Optional sanitizer run:

RUN_SANITIZERS=1 bash reproduce.sh

Evidence

  • Current main tested: a9f7a359a32e8cebceed6d689380db2d0f245120.
  • Main ASAN: read SEGV in GifSplitPalette at gif.h:349.
  • Main UBSAN: signed integer overflow at gif.h:343: 17664000 * 127 cannot be represented in int.
  • v3.1.15.0 ASAN/UBSAN reports the same source locations.
  • No public open PR was found for GifSplitPalette, GIFOutput, or this GIF palette integer overflow. Open TGA PRs checked were unrelated.

Root cause

During GIF output close, OpenImageIO writes the pending initialized canvas even after the TGA reader reported EOF. GIF palette construction then computes the split size with int arithmetic:

int subPixelsA = numPixels * (splitElt - firstElt) / (lastElt - firstElt);
pal->treeSplit[treeNode] = image[subPixelsA * 4 + splitCom];

For the PoC, numPixels is 17,664,000; multiplying by 127 overflows signed 32-bit int, corrupts subPixelsA, and leads to an out-of-bounds read.

Suggested fix

  • Use checked size_t/uint64_t arithmetic in the GIF palette splitter before converting to int.
  • Reject GIF outputs whose total pixel count exceeds the palette builder's safe range.
  • Clear the pending GIF frame or skip finish_subimage() when the input read failed.

PoC archive contents

poc.zip contains exactly these files:

poc.zip

  • poc/poc.tga — minimized 18-byte trigger.
  • reproduce.sh — product-binary reproduction script.
  • evidence/reproduce.log — latest non-sanitized original-binary reproduction output.
  • evidence/gdb_v3_orig_min_poc_gif.txt — v3 original GDB backtrace.
  • evidence/gdb_main_orig_min_poc_gif.txt — main original GDB backtrace.
  • evidence/v3_asan_gif.stderr — full v3 ASAN log.
  • evidence/v3_ubsan_gif.stderr — full v3 UBSAN log.
  • evidence/main_asan_gif.stderr — full main ASAN log.
  • evidence/main_ubsan_gif_vm2g.stderr — full main UBSAN log.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H

CVE ID

CVE-2026-65969

Weaknesses

Out-of-bounds Read

The product reads data past the end, or before the beginning, of the intended buffer. Learn more on MITRE.

Integer Overflow or Wraparound

The product performs a calculation that can produce an integer overflow or wraparound when the logic assumes that the resulting value will always be larger than the original value. This occurs when an integer value is incremented to a value that is too large to store in the associated representation. When this occurs, the value may become a very small or negative number. Learn more on MITRE.

Credits