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