Skip to content

Memory leak bugs when a new reference is only passed to a non-stealing API (static analyzer reports) #6323

Closed
@Snape3058

Description

@Snape3058
  • API PyDict_SetItemString does not steal a reference from the third argument.
  • API PyDict_SetItem does not steal a reference from the last argument.
  • API PyList_Append does not steal a reference from the second argument.
  • API PyDict_SetItem does not steal a reference from the third argument if the return value is not zero.

If a new reference is passed to the function without decreasing its refcnt then, it will lead to a memory leak.


Pattern 1: APIs returning a new reference are called directly as the third argument.

  • Internal Report ID: 1b7403
    PyDict_SetItemString(d, "new_count", PyLong_FromLong(arena->stats_new_count));
  • Internal Report ID: 6fa78e
    d, "allocated_blocks", PyLong_FromLong(arena->stats_allocated_blocks));
  • Internal Report ID: b43c87
    d, "reused_blocks", PyLong_FromLong(arena->stats_reused_blocks));
  • Internal Report ID: 1640ab
    d, "reallocated_blocks", PyLong_FromLong(arena->stats_reallocated_blocks));
  • Internal Report ID: 78d881
    PyDict_SetItemString(d, "freed_blocks", PyLong_FromLong(arena->stats_freed_blocks));
  • Internal Report ID: 6acded
    PyDict_SetItemString(d, "blocks_cached", PyLong_FromLong(arena->blocks_cached));
  • Internal Report ID: 15cbc4
    d, "jpeglib_version", PyUnicode_FromString(ImagingJpegVersion()));
  • Internal Report ID: a78d30
    d, "jp2klib_version", PyUnicode_FromString(ImagingJpeg2KVersion()));
  • Internal Report ID: 446850
    d, "libjpeg_turbo_version", PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION)));
  • Internal Report ID: 3c8041
    d, "imagequant_version", PyUnicode_FromString(ImagingImageQuantVersion()));
  • Internal Report ID: 1abe89
    d, "zlib_version", PyUnicode_FromString(ImagingZipVersion()));
  • Internal Report ID: b9e74a
    d, "libtiff_version", PyUnicode_FromString(ImagingTiffVersion()));
  • Internal Report ID: be23b5
    PyDict_SetItemString(d, "PILLOW_VERSION", PyUnicode_FromString(version));
  • Internal Report ID: 611fdf
    list_axis, "minimum", PyLong_FromLong(axis.minimum / 65536));
  • Internal Report ID: 7c0d23
    PyDict_SetItemString(list_axis, "default", PyLong_FromLong(axis.def / 65536));
  • Internal Report ID: b84747
    list_axis, "maximum", PyLong_FromLong(axis.maximum / 65536));
  • Internal Report ID: 3c802a
    PyDict_SetItemString(d, "__version", PyUnicode_FromString("0.1"));
  • Internal Report ID: 71bbbc
    d, "webpdecoder_version", PyUnicode_FromString(WebPDecoderVersion_str()));
  • Internal Report ID: 213466
    m, "HAVE_TRANSPARENCY", PyBool_FromLong(!WebPDecoderBuggyAlpha()));

Pattern 2: Intermediate variables are used to forward the argument.

  • Internal Report ID: e4a37b

New reference is returned here:

v = PyUnicode_FromFormat("%d.%d.%d", vn / 1000, (vn / 10) % 100, vn % 10);

PyObject is passed to non-stealing API here:
PyDict_SetItemString(d, "littlecms_version", v);


  • Internal Report ID: dc5fd5

New reference is returned here:

v = PyUnicode_FromFormat("%d.%d", vn / 1000, (vn / 10) % 100);

PyObject is passed to non-stealing API here:
PyDict_SetItemString(d, "littlecms_version", v);


  • Internal Report ID: 1e988b

New reference is returned here:

id = PyLong_FromLong((long)intent);

PyObject is passed to non-stealing API here:
PyDict_SetItem(result, id, entry);


  • Internal Report ID: 0ef1f7

New reference is returned here:

entry = Py_BuildValue(

PyObject is passed to non-stealing API here:
PyDict_SetItem(result, id, entry);


  • Internal Report ID: fce490

New reference is returned here:

axis_name = Py_BuildValue("y#", name.string, name.string_len);

PyObject is passed to non-stealing API here:
PyDict_SetItemString(list_axis, "name", axis_name);


  • Internal Report ID: d17f14

New reference is returned here:

v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch);

PyObject is passed to non-stealing API here:
PyDict_SetItemString(d, "freetype2_version", v);


  • Internal Report ID: 21a68f

New reference is returned here:

v = PyUnicode_FromString(raqm_version_string());

PyObject is passed to non-stealing API here:
PyDict_SetItemString(d, "raqm_version", v);


  • Internal Report ID: e80f52

New reference is returned here:

v = PyBool_FromLong(have_raqm);

PyObject is passed to non-stealing API here:
PyDict_SetItemString(d, "HAVE_RAQM", v);

PyDict_SetItemString(d, "HAVE_FRIBIDI", v);

PyDict_SetItemString(d, "HAVE_HARFBUZZ", v);


  • Internal Report ID: 29a870

New reference is returned here:

PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx);

PyObject is passed to non-stealing API here:
PyList_Append(ret, coordObj);


  • Internal Report ID: fddf55

New reference is returned here:

PyObject *coordObj = Py_BuildValue("(nn)", col_idx, row_idx);

PyObject is passed to non-stealing API here:
PyList_Append(ret, coordObj);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions