[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;
 }
 

AltStyle によって変換されたページ (->オリジナル) /