[Python-checkins] python/dist/src/Objects abstract.c,2.112,2.113
nascheme@users.sourceforge.net
nascheme@users.sourceforge.net
2002年12月30日 12:18:18 -0800
Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1:/tmp/cvs-serv10164/Objects
Modified Files:
abstract.c
Log Message:
Always try nb_* slots before trying sq_concat, sq_inplace_concat, sq_repeat,
andsq_inplace_repeat. This fixes a number of corner case bugs (see #624807).
Consolidate the int and long sequence repeat code. Before the change, integers
checked for integer overflow but longs did not.
Index: abstract.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v
retrieving revision 2.112
retrieving revision 2.113
diff -C2 -d -r2.112 -r2.113
*** abstract.c 12 Dec 2002 19:14:07 -0000 2.112
--- abstract.c 30 Dec 2002 20:18:15 -0000 2.113
***************
*** 406,421 ****
static PyObject *
binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
{
PyObject *result = binary_op1(v, w, op_slot);
if (result == Py_NotImplemented) {
! Py_DECREF(Py_NotImplemented);
! PyErr_Format(
! PyExc_TypeError,
! "unsupported operand type(s) for %s: '%s' and '%s'",
! op_name,
! v->ob_type->tp_name,
! w->ob_type->tp_name);
! return NULL;
}
return result;
--- 406,426 ----
static PyObject *
+ binop_type_error(PyObject *v, PyObject *w, const char *op_name)
+ {
+ PyErr_Format(PyExc_TypeError,
+ "unsupported operand type(s) for %s: '%s' and '%s'",
+ op_name,
+ v->ob_type->tp_name,
+ w->ob_type->tp_name);
+ return NULL;
+ }
+
+ static PyObject *
binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
{
PyObject *result = binary_op1(v, w, op_slot);
if (result == Py_NotImplemented) {
! Py_DECREF(result);
! return binop_type_error(v, w, op_name);
}
return result;
***************
*** 596,600 ****
BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>")
BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-")
- BINARY_FUNC(PyNumber_Multiply, nb_multiply, "*")
BINARY_FUNC(PyNumber_Divide, nb_divide, "/")
BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()")
--- 601,604 ----
***************
*** 612,621 ****
if (result == Py_NotImplemented) {
Py_DECREF(result);
! PyErr_Format(
! PyExc_TypeError,
! "unsupported operand types for +: '%s' and '%s'",
! v->ob_type->tp_name,
! w->ob_type->tp_name);
! result = NULL;
}
}
--- 616,620 ----
if (result == Py_NotImplemented) {
Py_DECREF(result);
! return binop_type_error(v, w, "+");
}
}
***************
*** 623,626 ****
--- 622,687 ----
}
+ static PyObject *
+ sequence_repeat(intargfunc repeatfunc, PyObject *seq, PyObject *n)
+ {
+ long count;
+ if (PyInt_Check(n)) {
+ count = PyInt_AsLong(n);
+ }
+ else if (PyLong_Check(n)) {
+ count = PyLong_AsLong(n);
+ if (count == -1 && PyErr_Occurred())
+ return NULL;
+ }
+ else {
+ return type_error(
+ "can't multiply sequence to non-int");
+ }
+ #if LONG_MAX != INT_MAX
+ if (count > INT_MAX) {
+ PyErr_SetString(PyExc_ValueError,
+ "sequence repeat count too large");
+ return NULL;
+ }
+ else if (count < INT_MIN)
+ count = INT_MIN;
+ /* XXX Why don't I either
+
+ - set count to -1 whenever it's negative (after all,
+ sequence repeat usually treats negative numbers
+ as zero(); or
+
+ - raise an exception when it's less than INT_MIN?
+
+ I'm thinking about a hypothetical use case where some
+ sequence type might use a negative value as a flag of
+ some kind. In those cases I don't want to break the
+ code by mapping all negative values to -1. But I also
+ don't want to break e.g. []*(-sys.maxint), which is
+ perfectly safe, returning []. As a compromise, I do
+ map out-of-range negative values.
+ */
+ #endif
+ return (*repeatfunc)(seq, (int)count);
+ }
+
+ PyObject *
+ PyNumber_Multiply(PyObject *v, PyObject *w)
+ {
+ PyObject *result = binary_op1(v, w, NB_SLOT(nb_multiply));
+ if (result == Py_NotImplemented) {
+ PySequenceMethods *mv = v->ob_type->tp_as_sequence;
+ PySequenceMethods *mw = w->ob_type->tp_as_sequence;
+ if (mv && mv->sq_repeat) {
+ return sequence_repeat(mv->sq_repeat, v, w);
+ }
+ else if (mw && mw->sq_repeat) {
+ return sequence_repeat(mw->sq_repeat, w, v);
+ }
+ result = binop_type_error(v, w, "*");
+ }
+ return result;
+ }
+
PyObject *
PyNumber_FloorDivide(PyObject *v, PyObject *w)
***************
*** 669,674 ****
static PyObject *
! binary_iop(PyObject *v, PyObject *w, const int iop_slot, const int op_slot,
! const char *op_name)
{
PyNumberMethods *mv = v->ob_type->tp_as_number;
--- 730,734 ----
static PyObject *
! binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot)
{
PyNumberMethods *mv = v->ob_type->tp_as_number;
***************
*** 683,687 ****
}
}
! return binary_op(v, w, op_slot, op_name);
}
--- 743,759 ----
}
}
! return binary_op1(v, w, op_slot);
! }
!
! 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);
! if (result == Py_NotImplemented) {
! Py_DECREF(result);
! return binop_type_error(v, w, op_name);
! }
! return result;
}
***************
*** 719,734 ****
PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
{
! binaryfunc f = NULL;
!
! if (v->ob_type->tp_as_sequence != NULL) {
! if (HASINPLACE(v))
! f = v->ob_type->tp_as_sequence->sq_inplace_concat;
! if (f == NULL)
! f = v->ob_type->tp_as_sequence->sq_concat;
! if (f != NULL)
! return (*f)(v, w);
}
! return binary_iop(v, w, NB_SLOT(nb_inplace_add),
! NB_SLOT(nb_add), "+=");
}
--- 791,811 ----
PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
{
! PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_add),
! NB_SLOT(nb_add));
! if (result == Py_NotImplemented) {
! PySequenceMethods *m = v->ob_type->tp_as_sequence;
! Py_DECREF(result);
! if (m != NULL) {
! binaryfunc f = NULL;
! if (HASINPLACE(v))
! f = m->sq_inplace_concat;
! if (f == NULL)
! f = m->sq_concat;
! if (f != NULL)
! return (*f)(v, w);
! }
! result = binop_type_error(v, w, "+=");
}
! return result;
}
***************
*** 736,763 ****
PyNumber_InPlaceMultiply(PyObject *v, PyObject *w)
{
! PyObject * (*g)(PyObject *, int) = NULL;
! if (HASINPLACE(v) &&
! v->ob_type->tp_as_sequence &&
! (g = v->ob_type->tp_as_sequence->sq_inplace_repeat) &&
! !(v->ob_type->tp_as_number &&
! v->ob_type->tp_as_number->nb_inplace_multiply))
! {
! long n;
! if (PyInt_Check(w)) {
! n = PyInt_AsLong(w);
! }
! else if (PyLong_Check(w)) {
! n = PyLong_AsLong(w);
! if (n == -1 && PyErr_Occurred())
! return NULL;
}
! else {
! return type_error(
! "can't multiply sequence to non-int");
}
! return (*g)(v, (int)n);
}
! return binary_iop(v, w, NB_SLOT(nb_inplace_multiply),
! NB_SLOT(nb_multiply), "*=");
}
--- 813,841 ----
PyNumber_InPlaceMultiply(PyObject *v, PyObject *w)
{
! PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_multiply),
! NB_SLOT(nb_multiply));
! if (result == Py_NotImplemented) {
! intargfunc f = NULL;
! PySequenceMethods *mv = v->ob_type->tp_as_sequence;
! PySequenceMethods *mw = w->ob_type->tp_as_sequence;
! Py_DECREF(result);
! if (mv != NULL) {
! if (HASINPLACE(v))
! f = mv->sq_inplace_repeat;
! if (f == NULL)
! f = mv->sq_repeat;
! if (f != NULL)
! return sequence_repeat(f, v, w);
}
! else if (mw != NULL) {
! /* Note that the right hand operand should not be
! * mutated in this case so sq_inplace_repeat is not
! * used. */
! if (mw->sq_repeat)
! return sequence_repeat(mw->sq_repeat, w, v);
}
! result = binop_type_error(v, w, "*=");
}
! return result;
}