Skip to content

[BUG] Reference leak: tag_type new ref from PyDict_GetItemRef never DECREF'd in PyImaging_LibTiffEncoderNew #9700

@Fuyugithub

Description

@Fuyugithub

Bug Description

In src/encode.c, PyImaging_LibTiffEncoderNew calls PyDict_GetItemRef to look up each tag's type from the types dict. PyDict_GetItemRef returns a new reference, but the returned tag_type object is never released, leaking one reference per tag entry on every TIFF save that uses a types dict.

Location

src/encode.c:792–802

Code

PyObject *tag_type;
if (PyDict_GetItemRef(types, key, &tag_type) < 0) { ... }
if (tag_type) {
    int type_int = PyLong_AsLong(tag_type);
    if (type_int >= TIFF_BYTE && type_int <= TIFF_LONG8) {
        type = (TIFFDataType)type_int;
    }
    // BUG: tag_type (NEW reference from PyDict_GetItemRef) is never Py_DECREF'd
}

PyDict_GetItemRef (unlike the deprecated PyDict_GetItem) always returns a new reference. The caller is responsible for releasing it. No Py_DECREF(tag_type) exists anywhere in this branch.

Impact

  • One PyLong object leaked per tag with a custom type entry, per TIFF save call
  • In tight loops saving many TIFF files with custom tag types, this causes unbounded memory growth
  • Severity: HIGH (leaks on every affected TIFF save)

Suggested Fix

Add Py_DECREF(tag_type); after the if (tag_type) block:

if (tag_type) {
    int type_int = PyLong_AsLong(tag_type);
    if (type_int >= TIFF_BYTE && type_int <= TIFF_LONG8) {
        type = (TIFFDataType)type_int;
    }
    Py_DECREF(tag_type);   // release the new reference
}

Environment

  • Pillow version: current main
  • Affected: any Image.save(..., format="TIFF") call that passes a tiffinfo dict with a types sub-dict

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions