classification
Title: NULL pointer dereference in listsort() with key function
Type: crash Stage: resolved
Components: Interpreter Core Versions: Python 3.6, Python 3.5, Python 3.2, Python 3.3, Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Arfrever, benjamin.peterson, christian.heimes, python-dev
Priority: high Keywords:

Created on 2015-04-23 21:03 by benjamin.peterson, last changed 2015-04-23 23:19 by Arfrever. This issue is now closed.

Messages (2)
msg241889 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2015-04-23 21:03
Found by Christian Heimes:

Coverity has found a flaw in Objects/listobject.c:listsort() that
eventually leads to a NULL pointer dereference. Because NULL pointer
dereferences can lead to exploits or DoS vulnerabilities I'm reporting
the error on PSRT first. The error is on a code path that can be
triggered by a remote attacker, although not that easily. All Python 3
versions are affected, Python 2.7 looks save.

The problematic code line is
https://hg.python.org/cpython/file/bc1a178b3bc8/Objects/listobject.c#l19
65
. The code fails to restore self->ob_item to saved_ob_item when
PyMem_MALLOC() fails. Subsequent access to the same list object will
dereference self->ob_item (which is still NULL) and cause a segfault.

A remote attack might be able to trigger the segfault with a large
data set. All it takes is an application that sorts this large data
set with list.sort() and a custom key function. When Python runs out
of memory just in the right spot ... CRASH.

Additionally there is another bug, too. list.sort() doesn't set an
exception when PyMem_MALLOC() fails. A fix for both issues is simple
and straight forward:

diff -r bc1a178b3bc8 Objects/listobject.c
- --- a/Objects/listobject.c      Sat Apr 18 05:54:02 2015 +0200
+++ b/Objects/listobject.c      Sat Apr 18 06:29:02 2015 +0200
@@ -1961,8 +1961,10 @@
             keys = &ms.temparray[saved_ob_size+1];
         else {
             keys = PyMem_MALLOC(sizeof(PyObject *) * saved_ob_size);
- -            if (keys == NULL)
- -                return NULL;
+            if (keys == NULL) {
+                PyErr_NoMemory();
+                goto keyfunc_fail;
+            }
         }

         for (i = 0; i < saved_ob_size ; i++) {
msg241890 - (view) Author: Roundup Robot (python-dev) Date: 2015-04-23 21:08
New changeset 91096d27c802 by Benjamin Peterson in branch '3.2':
properly handle malloc failure (closes #24044)
https://hg.python.org/cpython/rev/91096d27c802

New changeset 0d8f15053f42 by Benjamin Peterson in branch '3.3':
merge 3.2 (#24044)
https://hg.python.org/cpython/rev/0d8f15053f42

New changeset 80485b8e43cd by Benjamin Peterson in branch '3.4':
merge 3.3 (#24044)
https://hg.python.org/cpython/rev/80485b8e43cd

New changeset bd656916586f by Benjamin Peterson in branch 'default':
merge 3.4 (#24044)
https://hg.python.org/cpython/rev/bd656916586f
History
Date User Action Args
2015-04-23 23:19:37Arfreversetnosy: + Arfrever
2015-04-23 21:08:39benjamin.petersonlinkissue24038 superseder
2015-04-23 21:08:18benjamin.petersonsetversions: - Python 2.7
2015-04-23 21:08:08python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg241890

resolution: fixed
stage: resolved
2015-04-23 21:03:08benjamin.petersoncreate