classification
Title: Reference counting bug in PyArg_ParseTuple and PyArg_ParseTupleAndKeywords
Type: crash Stage: needs patch
Components: Interpreter Core Versions: Python 3.4, Python 3.3, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: abacabadabacaba, belopolsky, billm, georg.brandl, gregory.p.smith, loewis, python-dev, serhiy.storchaka
Priority: high Keywords: patch

Created on 2009-05-22 08:18 by billm, last changed 2014-10-14 16:30 by skrah.

Files
File name Uploaded Description Edit
python-bug-01.patch billm, 2009-05-22 08:18 Patch to fix the problem
test-resource.py abacabadabacaba, 2010-11-16 12:33 Test for Modules/resource.c
test-ctypes.py abacabadabacaba, 2010-11-16 12:34 Test for Modules/_ctypes/_ctypes.c
test-functools.py abacabadabacaba, 2010-11-16 12:35 Test for Modules/_functoolsmodule.c (py3k only)
issue6083.diff belopolsky, 2011-01-14 06:42 review
PyArg_ParseTuple_refcount.patch serhiy.storchaka, 2012-10-14 20:18 review
Messages (15)
msg88181 - (view) Author: Bill McCloskey (billm) Date: 2009-05-22 08:18
The code for resource_setrlimit in Modules/resource.c does not handle
reference counting properly. The following Python code segfaults for me
on Ubuntu 8.10 in Python 2.5.2 and also a custom-built 2.6.1.

--
import resource

l = [0, 0]

class MyNum:
    def __int__(self):
        l[1] = 20
        return 10

    def __del__(self):
        print 'byebye', self

l[0] = MyNum()
l[1] = MyNum()
resource.setrlimit(resource.RLIMIT_CPU, l)
--

The problem is that setrlimit gets its arguments by calling:
   PyArg_ParseTuple(args, "i(OO):setrlimit", 
                    &resource, &curobj, &maxobj)
The references curobj and maxobj are borrowed. The second argument can
be passed as a mutable list rather than a tuple, so it's possible to
update the list in the middle of setrlimit, causing maxobj to be
destroyed before setrlimit is done with it.

I've attached a patch that INCREFs both variables immediately after
parsing them to avoid this problem.

In my opinion it seems dangerous to allow format strings with the 'O'
specifier appearing in parentheses. You normally expect that objects
returned from PyArg_ParseTuple are pretty safe, but the fact that the
inner sequence may be mutable violates this assumption. Might it make
sense to ban this use case? I only found one other instance of it in the
Python source tree, inside ctypes. This one may also be a crashing
bug--I didn't look at it carefully enough.
msg88204 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-05-22 17:09
That is a good point.  IMHO we'll be fine with a warning in the docs,
and fixing our own two instances.  Martin, what do you think?
msg88215 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-05-22 20:14
IMO, any refcounting bug has the potential as a security risk. So I
think we should deprecate this with a warning, and eventually remove it,
as billm proposes.

It's probably debatable whether to backport the warning to 2.6 or
earlier; I think we shouldn't, as many applications are probably valid.
msg121285 - (view) Author: Evgeny Kapun (abacabadabacaba) Date: 2010-11-16 12:33
Actually, this can't be fixed without modifying C API methods PyArg_ParseTuple and PyArg_ParseTupleAndKeywords, because it's possible to make an object deallocated before PyArg_ParseTuple returns, so Py_INCREF immediately after parsing would be already too late.

Here are my test cases:
test-resource.py - in Modules/resource.c, and python-bug-01.patch won't work against it.
test-ctypes.py - in Modules/_ctypes/_ctypes.c.
test-functools.py - in Modules/_functoolsmodule.c (py3k only).
msg126226 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2011-01-14 04:55
Let me summarize the issue: the PyArg_ParseTuple format code 'O' returns a borrowed reference.  However, when the 'O' code appears inside parenthesis, there may not be an object to hold the reference to borrow from.  This is what happens in the test-functools.py crasher:  partial.__setstate__() takes a 4-tuple argument that is unpacked using a "(OOOO)" format.  The test case passes an instance instead of a tuple that supports the sequence methods, but does not hold the reference to the "items" that its []-operator returns.  This is not a problem at the top level because args argument to PyArg_ParseTuple is always a real tuple.

I think that rather than deprecating the use of 'O' format inside parentheses, "(..O..)" unpacking should reject to unpack arguments other than tuples or maybe lists.
msg126234 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2011-01-14 06:42
Attached patch passes the regrtest and makes test-functools.py raise an exception rather than crash.  The proposed change will make functions like partial.__setstate__ require tuple argument even though currently it would accept any container.  This is not an issue with __setstate__ because it should only be called with arguments produced by __reduce__ and in the case of partial, __reduce__ produces state as a tuple.  Other functions may need to be modified if they need to continue to accept arbitrary sequences.
msg172912 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2012-10-14 20:18
Here is a patch which get rid of all three PyArg_ParseTuple usage with parsing nested sequences. Thanks Evgeny for reproducers.
msg181297 - (view) Author: Gregory P. Smith (gregory.p.smith) * (Python committer) Date: 2013-02-03 20:31
Serhiy's patch looks good to me.
msg181316 - (view) Author: Roundup Robot (python-dev) Date: 2013-02-04 11:05
New changeset a4c85f9b8f58 by Serhiy Storchaka in branch '2.7':
Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
http://hg.python.org/cpython/rev/a4c85f9b8f58

New changeset 4bac47eb444c by Serhiy Storchaka in branch '3.2':
Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
http://hg.python.org/cpython/rev/4bac47eb444c

New changeset e0ee10f27e5f by Serhiy Storchaka in branch '3.3':
Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
http://hg.python.org/cpython/rev/e0ee10f27e5f

New changeset 3e3a7d825736 by Serhiy Storchaka in branch 'default':
Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
http://hg.python.org/cpython/rev/3e3a7d825736
msg181327 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-02-04 13:33
I do not have possibility and desires blind-repair a test on alien platform, so just temporarily disable a new test in Lib/ctypes/test/test_returnfuncptrs.py on Windows. If someone has a desire to fix it fell free to do this.

I do not close this issue because committed patch only fix existing crashes in Python. There should be plenty of such bugs in third-party code. We have to deprecate this unsafe feature or reject any sequences except tuple as Alexander proposed.
msg181592 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2013-02-07 11:41
The FreeBSD 6.4 bot is failing, too. Note that the other functions
in test_returnfuncptrs.py do this in order to get strchr():

    dll = CDLL(_ctypes_test.__file__)
    get_strchr = dll.get_strchr
    get_strchr.restype = CFUNCTYPE(c_char_p, c_char_p, c_char)
    strchr = get_strchr()
msg181600 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-02-07 13:05
There are 6 different ways to get a function (see comment around PyCFuncPtr_new() in Modules/_ctypes/_ctypes.c). The other tests just use other ways.

I'm more carefully read ctype code and found my mistake. Need to import "my_strchr", and not "strchr".
msg182108 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-02-14 16:11
FreeBSD 6.4 and Windows test failures was fixed in changesets 8fb98fb758e8 and ec70abe8c886.
msg182110 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-02-14 16:16
Oh, I shouldn't close this until this dangerous feature will be deprecated.
msg201454 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-10-27 12:49
Accepting an arbitrary sequence when "(...)" is used in the format string was introduced in changeset 0ef1071cb7fe.
History
Date User Action Args
2014-10-14 16:30:29skrahsetnosy: - skrah
2014-01-25 09:03:32serhiy.storchakasetpriority: normal -> high
2013-10-27 12:49:10serhiy.storchakasetmessages: + msg201454
versions: - Python 3.2
2013-02-14 16:16:05serhiy.storchakasetstatus: closed -> open
messages: + msg182110

assignee: serhiy.storchaka ->
resolution: fixed ->
stage: resolved -> needs patch
2013-02-14 16:11:01serhiy.storchakasetstatus: open -> closed
messages: + msg182108

assignee: serhiy.storchaka
resolution: fixed
stage: needs patch -> resolved
2013-02-07 13:05:08serhiy.storchakasetmessages: + msg181600
2013-02-07 11:41:03skrahsetnosy: + skrah
messages: + msg181592
2013-02-04 13:34:37serhiy.storchakasetassignee: serhiy.storchaka -> (no value)
2013-02-04 13:33:24serhiy.storchakasetstage: patch review -> needs patch
messages: + msg181327
versions: - Python 3.1
2013-02-04 11:05:35python-devsetnosy: + python-dev
messages: + msg181316
2013-02-03 20:31:35gregory.p.smithsetnosy: + gregory.p.smith
messages: + msg181297
2012-12-29 22:19:42serhiy.storchakasetassignee: serhiy.storchaka
2012-10-14 20:19:02serhiy.storchakasetversions: + Python 3.3, Python 3.4
2012-10-14 20:18:27serhiy.storchakasetfiles: + PyArg_ParseTuple_refcount.patch
nosy: + serhiy.storchaka
messages: + msg172912

2011-01-14 06:42:07belopolskysetfiles: + issue6083.diff

messages: + msg126234
nosy: loewis, georg.brandl, belopolsky, billm, abacabadabacaba
stage: needs patch -> patch review
2011-01-14 04:55:18belopolskysetnosy: + belopolsky

messages: + msg126226
stage: needs patch
2010-11-16 12:35:15abacabadabacabasetfiles: + test-functools.py
2010-11-16 12:34:29abacabadabacabasetfiles: + test-ctypes.py
2010-11-16 12:33:46abacabadabacabasetfiles: + test-resource.py
title: Reference counting bug in setrlimit -> Reference counting bug in PyArg_ParseTuple and PyArg_ParseTupleAndKeywords
nosy: + abacabadabacaba

messages: + msg121285

components: + Interpreter Core, - Extension Modules
2010-08-03 20:53:23terry.reedysetversions: + Python 3.1, Python 2.7, Python 3.2, - Python 2.6, Python 2.5
2009-05-22 20:14:53loewissetassignee: loewis -> (no value)
2009-05-22 20:14:45loewissetmessages: + msg88215
2009-05-22 17:09:01georg.brandlsetassignee: loewis

messages: + msg88204
nosy: + loewis, georg.brandl
2009-05-22 08:18:55billmcreate