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 deref in binary_iop1 function
Type: Stage:
Components: Interpreter Core Versions: Python 3.6
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: Emin Ghuliev, r.david.murray
Priority: normal Keywords:

Created on 2016-07-07 15:48 by Emin Ghuliev, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
repro Emin Ghuliev, 2016-07-07 15:48
Messages (4)
msg269940 - (view) Author: Emin Ghuliev (Emin Ghuliev) Date: 2016-07-07 15:48
Python VM parses "0x3b" opcode (INPLACE_MODULO) in the bytecode file. Subsequently VM parses left and right arguments of the opcode (0x3b). If left and right arguments doesn't exists in the bytecode file that causes a segmentation fault. Which triggered by the binary_iop1 function.


PyEval_EvalFrameEx() at Python/ceval.c:1749

        TARGET(INPLACE_MODULO) {
            PyObject *right = POP();
            PyObject *left = TOP();
            PyObject *mod = PyNumber_InPlaceRemainder(left, right); < left = 0, right = 0;

Then INPLACE_MODULO opcode is passed two arguments into PyNumber_InPlaceRemainder. However, in order to call the binary_iop:

PyNumber_InPlaceRemainder at Objects/abstract.c:1102

PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
{
    return binary_iop(v, w, NB_SLOT(nb_inplace_remainder),
                            NB_SLOT(nb_remainder), "%=");
}

Subsequently the binary_iop function is passed "v" argument into the binary_iop1:

binary_iop at Objects/abstract.c:1005

static PyObject *
binary_iop(PyObject *v, PyObject *w, const int iop_slot, const int op_slot,
                const char *op_name)
{
    PyObject *result = binary_iop1(v, w, iop_slot, op_slot); # v = 0 and call the binary_iop1 function
    if (result == Py_NotImplemented) {
        Py_DECREF(result);
        return binop_type_error(v, w, op_name);
    }
    return result;
}

binary_iop1 at Objects/abstract.c:988

static PyObject *
binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot)
{
    PyNumberMethods *mv = v->ob_type->tp_as_number; // dereference object < -- > v = 0x0
    if (mv != NULL) {
        binaryfunc slot = NB_BINOP(mv, iop_slot);
        if (slot) {
            PyObject *x = (slot)(v, w);
            if (x != Py_NotImplemented) {
                return x;
            }
            Py_DECREF(x);
        }
    }
    return binary_op1(v, w, op_slot);
}

The binary_iop1 function doesn't check "v" field and dereference it.

<PyNumber_InPlaceRemainder+16>  mov    rsi,QWORD PTR [rdi+0x8] = 0x8 byte -> ob_type 

$rdi register = 0x0


Program received signal SIGSEGV, Segmentation fault.
msg269942 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-07-07 15:51
Are you saying python generated an invalid bytecode file?
msg269944 - (view) Author: Emin Ghuliev (Emin Ghuliev) Date: 2016-07-07 16:03
Nope, invalid bytecode file generated by fuzzer for the purpose of bug researching. Just python doesn't determine whether a variable is empty or valid.
msg269946 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-07-07 16:11
Well, unless you can find a way to reproduce it with python code, it isn't interesting to us.
History
Date User Action Args
2022-04-11 14:58:33adminsetgithub: 71649
2016-07-07 16:20:13Emin Ghulievsetstatus: pending -> closed
resolution: not a bug -> wont fix
2016-07-07 16:11:53r.david.murraysetstatus: open -> pending
resolution: not a bug
messages: + msg269946
2016-07-07 16:03:38Emin Ghulievsetmessages: + msg269944
2016-07-07 15:51:44r.david.murraysetnosy: + r.david.murray
messages: + msg269942
2016-07-07 15:48:13Emin Ghulievcreate