[Python-checkins] CVS: python/dist/src/Objects
structseq.c,1.3.6.1,1.3.6.2
Neal Norwitz
neal@metaslash.com
Thu, 07 Mar 2002 07:59:07 -0500
Do you need to do:
Py_XDECREF(dict);
in all the places you Py_DECREF(arg)?
Neal
--
Michael Hudson wrote:
>
> Update of /cvsroot/python/python/dist/src/Objects
> In directory usw-pr-cvs1:/tmp/cvs-serv22453
>
> Modified Files:
> Tag: release22-maint
> structseq.c
> Log Message:
> After some thinking, I decided to move all of this across onto
> the branch. I don't think it can break code, so the only risk
> is introducing new bugs. In that vein, can I ask -checkins readers
> who have time to carefully look this over, check my refcounts &c?
> TIA.
>
> backport my checkin of
> revision 1.5 of structseq.c
>
> 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.3.6.1
> retrieving revision 1.3.6.2
> diff -C2 -d -r1.3.6.1 -r1.3.6.2
> *** structseq.c 5 Mar 2002 14:00:52 -0000 1.3.6.1
> --- structseq.c 7 Mar 2002 10:16:43 -0000 1.3.6.2
> ***************
> *** 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;
> }