diff options
author | Stefan Krah <skrah@bytereef.org> | 2016-07-17 12:01:42 (GMT) |
---|---|---|
committer | Stefan Krah <skrah@bytereef.org> | 2016-07-17 12:01:42 (GMT) |
commit | 8c126f17f09eeb75d3d3c9737150384cd1dd9c03 (patch) | |
tree | deb229d3647b9950ffb59999ebc2fe0ddba772c7 /Modules/_decimal/_decimal.c | |
parent | 80ab069f1b040b7418833d9c1facf77ad2bd4363 (diff) | |
download | cpython-8c126f17f09eeb75d3d3c9737150384cd1dd9c03.zip cpython-8c126f17f09eeb75d3d3c9737150384cd1dd9c03.tar.gz cpython-8c126f17f09eeb75d3d3c9737150384cd1dd9c03.tar.bz2 |
Issue #26974: Fix segfault in the presence of absurd subclassing. Proactively
eliminate all internal uses of overridden methods.
Diffstat (limited to 'Modules/_decimal/_decimal.c')
-rw-r--r-- | Modules/_decimal/_decimal.c | 50 |
1 files changed, 47 insertions, 3 deletions
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 22053b4..e15941a 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2208,6 +2208,14 @@ PyDecType_FromLongExact(PyTypeObject *type, const PyObject *pylong, return dec; } +/* External C-API functions */ +static binaryfunc _py_long_multiply; +static binaryfunc _py_long_floor_divide; +static ternaryfunc _py_long_power; +static unaryfunc _py_float_abs; +static PyCFunction _py_long_bit_length; +static PyCFunction _py_float_as_integer_ratio; + /* Return a PyDecObject or a subtype from a PyFloatObject. Conversion is exact. */ static PyObject * @@ -2258,13 +2266,13 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v, } /* absolute value of the float */ - tmp = PyObject_CallMethod(v, "__abs__", NULL); + tmp = _py_float_abs(v); if (tmp == NULL) { return NULL; } /* float as integer ratio: numerator/denominator */ - n_d = PyObject_CallMethod(tmp, "as_integer_ratio", NULL); + n_d = _py_float_as_integer_ratio(tmp, NULL); Py_DECREF(tmp); if (n_d == NULL) { return NULL; @@ -2272,7 +2280,7 @@ PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v, n = PyTuple_GET_ITEM(n_d, 0); d = PyTuple_GET_ITEM(n_d, 1); - tmp = PyObject_CallMethod(d, "bit_length", NULL); + tmp = _py_long_bit_length(d, NULL); if (tmp == NULL) { Py_DECREF(n_d); return NULL; @@ -5511,6 +5519,32 @@ static struct int_constmap int_constants [] = { #define CHECK_PTR(expr) \ do { if ((expr) == NULL) goto error; } while (0) + +static PyCFunction +cfunc_noargs(PyTypeObject *t, const char *name) +{ + struct PyMethodDef *m; + + if (t->tp_methods == NULL) { + goto error; + } + + for (m = t->tp_methods; m->ml_name != NULL; m++) { + if (strcmp(name, m->ml_name) == 0) { + if (!(m->ml_flags & METH_NOARGS)) { + goto error; + } + return m->ml_meth; + } + } + +error: + PyErr_Format(PyExc_RuntimeError, + "internal error: could not find method %s", name); + return NULL; +} + + PyMODINIT_FUNC PyInit__decimal(void) { @@ -5535,6 +5569,16 @@ PyInit__decimal(void) mpd_setminalloc(_Py_DEC_MINALLOC); + /* Init external C-API functions */ + _py_long_multiply = PyLong_Type.tp_as_number->nb_multiply; + _py_long_floor_divide = PyLong_Type.tp_as_number->nb_floor_divide; + _py_long_power = PyLong_Type.tp_as_number->nb_power; + _py_float_abs = PyFloat_Type.tp_as_number->nb_absolute; + ASSIGN_PTR(_py_float_as_integer_ratio, cfunc_noargs(&PyFloat_Type, + "as_integer_ratio")); + ASSIGN_PTR(_py_long_bit_length, cfunc_noargs(&PyLong_Type, "bit_length")); + + /* Init types */ PyDec_Type.tp_base = &PyBaseObject_Type; PyDecContext_Type.tp_base = &PyBaseObject_Type; |