This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Potential leak in PyFloat_AsDouble. Refcount error.
Type: resource usage Stage: resolved
Components: Interpreter Core Versions: Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Patrick Miller, amaury.forgeotdarc, mark.dickinson, python-dev
Priority: high Keywords:

Created on 2015-03-05 15:08 by Patrick Miller, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
floatobject.c-patch Patrick Miller, 2015-03-05 15:08 recreator and patch file
recreate.tar Patrick Miller, 2015-03-05 15:16 recreator and patch file
Messages (9)
msg237266 - (view) Author: Patrick Miller (Patrick Miller) Date: 2015-03-05 15:08
There is a reference counting error in PyFloat_AsDouble.

When the function calls the nb_float conversion, if the method does not return an actual float object, an exception is set, but the object is not collected.

--- Objects/floatobject.c	2014-10-08 04:18:15.000000000 -0400
+++ Objects/floatobject.c.patched	2015-03-05 09:17:15.171455648 -0500
@@ -214,6 +214,7 @@
     if (fo == NULL)
         return -1;
     if (!PyFloat_Check(fo)) {
+        Py_DECREF(fo);
         PyErr_SetString(PyExc_TypeError,
                         "nb_float should return float object");
         return -1;
msg237268 - (view) Author: Patrick Miller (Patrick Miller) Date: 2015-03-05 15:16
Here's a simple recreator... It returns a 100-meg string instead of a float.  The memory is leaked each time through the loop
msg237271 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2015-03-05 15:38
Simple script to reproduce the issue:

import sys, time
class C(object):
  def __float__(self):
    return ""
for x in range(10000):
  try:
    time.sleep(C())
  except TypeError:
    pass
  if x % 1000 == 0:
    print(sys.getrefcount(""))
msg237272 - (view) Author: Patrick Miller (Patrick Miller) Date: 2015-03-05 15:45
Shout out to amaury for a much simpler recreator :-)

Checked to see if the int conversion suffered the same problem... it does not as it is structured somewhat differently.  Note that it DOES do the proper DECREF (missing in PyFloat_AsDouble).


    result = nb->nb_int(integral);
    if (!result || PyLong_CheckExact(result))
        return (PyLongObject *)result;
    if (!PyLong_Check(result)) {
        PyErr_Format(PyExc_TypeError,
                     "__int__ returned non-int (type %.200s)",
                     result->ob_type->tp_name);
        Py_DECREF(result);
        return NULL;
    }
msg237275 - (view) Author: Patrick Miller (Patrick Miller) Date: 2015-03-05 16:52
This is also in the 2.7.x branch.  Same patch.
msg237335 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2015-03-06 08:40
Patch LGTM.  Marking as high priority.
msg237337 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2015-03-06 08:55
The patch should have a test before it goes in.  As an aside, it's a bit disturbing that we apparently don't have any code already in our test-suite that exercises this case.
msg237356 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2015-03-06 14:10
New changeset 30925a3b2324 by Benjamin Peterson in branch '3.4':
fix potential refleak in PyFloat_AsDouble (closes #23590)
https://hg.python.org/cpython/rev/30925a3b2324

New changeset f31b91b6683a by Benjamin Peterson in branch '2.7':
fix potential refleak in PyFloat_AsDouble (closes #23590)
https://hg.python.org/cpython/rev/f31b91b6683a

New changeset 4d9594018edd by Benjamin Peterson in branch 'default':
merge 3.4 (#23590)
https://hg.python.org/cpython/rev/4d9594018edd
msg237367 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2015-03-06 16:27
Thanks, Benjamin!
History
Date User Action Args
2022-04-11 14:58:13adminsetgithub: 67778
2015-03-06 16:27:00mark.dickinsonsetassignee: mark.dickinson ->
messages: + msg237367
2015-03-06 14:10:04python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg237356

resolution: fixed
stage: patch review -> resolved
2015-03-06 08:55:29mark.dickinsonsetmessages: + msg237337
2015-03-06 08:48:10mark.dickinsonsetassignee: mark.dickinson
2015-03-06 08:40:58mark.dickinsonsetpriority: normal -> high
nosy: + mark.dickinson
messages: + msg237335

2015-03-06 00:37:04pitrousetstage: patch review
type: behavior -> resource usage
versions: + Python 2.7, Python 3.5
2015-03-05 16:52:29Patrick Millersetmessages: + msg237275
2015-03-05 15:45:07Patrick Millersetmessages: + msg237272
2015-03-05 15:38:22amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg237271
2015-03-05 15:16:07Patrick Millersetfiles: + recreate.tar

messages: + msg237268
2015-03-05 15:08:15Patrick Millercreate