[Python-checkins] CVS: python/dist/src/Objects structseq.c,1.4,1.5

Michael Hudson mwh@users.sourceforge.net
Wed, 06 Mar 2002 09:07:51 -0800


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv20601

Modified Files:
	structseq.c 
Log Message:
Apply (my) patch:

[ 526072 ] pickling os.stat results round II

structseq's constructors can now take "invisible" fields in a dict.
Gave the constructors better error messages.
their __reduce__ method puts these fields in a dict.

(this is all in aid of getting os.stat_result's to pickle portably)

Also fixes

[ 526039 ] devious code can crash structseqs

Thought needed about how much of this counts as a bugfix.  Certainly 
#526039 needs to be fixed.



Index: structseq.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/structseq.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** structseq.c	5 Mar 2002 13:27:57 -0000	1.4
--- structseq.c	6 Mar 2002 17:07:49 -0000	1.5
***************
*** 85,121 ****
  {
  	PyObject *arg = NULL;
  	PyStructSequence *res = NULL;
! 	int len, required_len, i;
! 	static char *kwlist[] = {"sequence", 0};
! 	static char msgbuf[128];
  
! 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:structseq", 
! 					 kwlist, &arg))
  		return NULL;
  
! 	if (!PySequence_Check(arg)) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"constructor requires a sequence");
  		return NULL;
  	}
  
! 	len = PySequence_Length(arg);
! 	required_len = REAL_SIZE_TP(type);
! 	if (len != required_len) {
! 		PyOS_snprintf(
! 			msgbuf, sizeof(msgbuf),
! 			"constructor takes exactly %d arguments (%d given)",
! 			required_len,
! 			len);
! 		PyErr_SetString(PyExc_TypeError, msgbuf);
  		return NULL;
  	}
  
  	res = (PyStructSequence*) PyStructSequence_New(type);
  	for (i = 0; i < len; ++i) {
! 		/* INCREF???? XXXX */
! 		res->ob_item[i] = PySequence_GetItem(arg, i);
  	}
  	
  	return (PyObject*) res;
  }
--- 85,161 ----
  {
  	PyObject *arg = NULL;
+ 	PyObject *dict = NULL;
+ 	PyObject *ob;
  	PyStructSequence *res = NULL;
! 	int len, min_len, max_len, i;
! 	static char *kwlist[] = {"sequence", "dict", 0};
  
! 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq", 
! 					 kwlist, &arg, &dict))
  		return NULL;
  
! 	arg = PySequence_Fast(arg, "constructor requires a sequence");
! 
! 	if (!arg) {				
  		return NULL;
  	}
  
! 	if (dict && !PyDict_Check(dict)) {
! 		PyErr_Format(PyExc_TypeError, 
! 			     "%.500s() takes a dict as second arg, if any",
! 			     type->tp_name);
! 		Py_DECREF(arg);
  		return NULL;
  	}
  
+ 	len = PySequence_Fast_GET_SIZE(arg);
+ 	min_len = VISIBLE_SIZE_TP(type);
+ 	max_len = REAL_SIZE_TP(type);
+ 
+ 	if (min_len != max_len) {
+ 		if (len < min_len) {
+ 			PyErr_Format(PyExc_TypeError, 
+ 	       "%.500s() takes an at least %d-sequence (%d-sequence given)",
+ 				     type->tp_name, min_len, len);
+ 			Py_DECREF(arg);
+ 			return NULL;
+ 		}
+ 
+ 		if (len > max_len) {
+ 			PyErr_Format(PyExc_TypeError, 
+ 	       "%.500s() takes an at most %d-sequence (%d-sequence given)",
+ 				     type->tp_name, max_len, len);
+ 			Py_DECREF(arg);
+ 			return NULL;
+ 		}
+ 	} 
+ 	else {
+ 		if (len != min_len) {
+ 			PyErr_Format(PyExc_TypeError, 
+ 	       "%.500s() takes a %d-sequence (%d-sequence given)",
+ 				     type->tp_name, min_len, len);
+ 			Py_DECREF(arg);
+ 			return NULL;
+ 		}
+ 	}
+ 
  	res = (PyStructSequence*) PyStructSequence_New(type);
  	for (i = 0; i < len; ++i) {
! 		PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
! 		Py_INCREF(v);
! 		res->ob_item[i] = v;
! 	}
! 	for (; i < max_len; ++i) {
! 		if (dict && (ob = PyDict_GetItemString(
! 			dict, type->tp_members[i].name))) {
! 		}
! 		else {
! 			ob = Py_None;
! 		}
! 		Py_INCREF(ob);
! 		res->ob_item[i] = ob;
  	}
  	
+ 	Py_DECREF(arg);
  	return (PyObject*) res;
  }
***************
*** 193,211 ****
  {
  	PyObject* tup;
! 	long n_fields;
  	int i;
  	
  	n_fields = REAL_SIZE(self);
! 	tup = PyTuple_New(n_fields);
  	if (!tup) {
  		return NULL;
  	}
  
! 	for (i = 0; i < n_fields; i++) {
  		Py_INCREF(self->ob_item[i]);
  		PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
  	}
  	
! 	return Py_BuildValue("(O(O))", self->ob_type, tup);
  }
  
--- 233,264 ----
  {
  	PyObject* tup;
! 	PyObject* dict;
! 	long n_fields, n_visible_fields;
  	int i;
  	
  	n_fields = REAL_SIZE(self);
! 	n_visible_fields = VISIBLE_SIZE(self);
! 	tup = PyTuple_New(n_visible_fields);
  	if (!tup) {
  		return NULL;
  	}
  
! 	dict = PyDict_New();
! 	if (!dict) {
! 		Py_DECREF(tup);
! 		return NULL;
! 	}
! 
! 	for (i = 0; i < n_visible_fields; i++) {
  		Py_INCREF(self->ob_item[i]);
  		PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
  	}
  	
! 	for (; i < n_fields; i++) {
! 		PyDict_SetItemString(dict, self->ob_type->tp_members[i].name,
! 				     self->ob_item[i]);
! 	}
! 
! 	return Py_BuildValue("(O(OO))", self->ob_type, tup, dict);
  }