Skip to content

Leak: _zstd.ZstdDecompressor() leaks a reference on invalid option key #148651

Closed

Description

@mjbommar

Bug report

Bug description:

Summary

Modules/_zstd/decompressor.c is missing a Py_DECREF(value) before
the early return when PyLong_AsInt(key) fails. The identical code in
Modules/_zstd/compressor.c has the fix.

Likely easy to miss other than very long running services that slowly
leak.

decompressor.c (buggy):

Py_INCREF(key);                          // line 109
Py_INCREF(value);                        // line 110
int key_v = PyLong_AsInt(key);           // line 111
Py_DECREF(key);                          // line 112
if (key_v == -1 && PyErr_Occurred()) {
    return -1;                           // line 114 -- leaks value
}

compressor.c (correct):

Py_INCREF(key);                          // line 150
Py_INCREF(value);                        // line 151
int key_v = PyLong_AsInt(key);           // line 152
Py_DECREF(key);                          // line 153
if (key_v == -1 && PyErr_Occurred()) {
    Py_DECREF(value);                    // line 158 -- present here
    return -1;
}

Reproducer

import _zstd, sys, gc

class Marker:
    pass

val = Marker()
baseline = sys.getrefcount(val)

for _ in range(100):
    try:
        _zstd.ZstdDecompressor(options={"bad_key": val})
    except Exception:
        pass

gc.collect()
after = sys.getrefcount(val)
print(f"baseline refcount: {baseline}")
print(f"after 100 error triggers: {after}")
print(f"leaked refs: {after - baseline}")

Output:

baseline refcount: 2
after 100 error triggers: 102
leaked refs: 100

Each call leaks exactly one reference to value.

Related

Proposed Fix

Just add Py_DECREF(value); before return -1 at decompressor.c line 114. Happy to submit that as a PR if you want.

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Activity

  1. StanFromIreland commented on Apr 16, 2026

    @StanFromIreland
    Member

    Happy to submit that as a PR if you want.

    The fix seems correct to me, go ahead! :-)

  2. added 3 commits that reference this issue on Apr 16, 2026
  3. added a commit that references this issue on Apr 17, 2026
  4. added a commit that references this issue on Apr 17, 2026
  5. added a commit that references this issue on Apr 17, 2026
  6. added a commit that references this issue on Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions