diff options
Diffstat (limited to 'Python/getargs.c')
| -rw-r--r-- | Python/getargs.c | 420 | 
1 files changed, 217 insertions, 203 deletions
| diff --git a/Python/getargs.c b/Python/getargs.c index 0069671..17c4ee5 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -33,16 +33,33 @@ PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,  #define FLAG_COMPAT 1  #define FLAG_SIZE_T 2 +typedef int (*destr_t)(PyObject *, void *); + + +/* Keep track of "objects" that have been allocated or initialized and +   which will need to be deallocated or cleaned up somehow if overall +   parsing fails. +*/ +typedef struct { +  void *item; +  destr_t destructor; +} freelistentry_t; + +typedef struct { +  int first_available; +  freelistentry_t *entries; +} freelist_t; +  /* Forward */  static int vgetargs1(PyObject *, const char *, va_list *, int);  static void seterror(int, const char *, int *, const char *, const char *);  static char *convertitem(PyObject *, const char **, va_list *, int, int *, -                         char *, size_t, PyObject **); +                         char *, size_t, freelist_t *);  static char *converttuple(PyObject *, const char **, va_list *, int, -                          int *, char *, size_t, int, PyObject **); +                          int *, char *, size_t, int, freelist_t *);  static char *convertsimple(PyObject *, const char **, va_list *, int, char *, -                           size_t, PyObject **); +                           size_t, freelist_t *);  static Py_ssize_t convertbuffer(PyObject *, void **p, char **);  static int getbuffer(PyObject *, Py_buffer *, char**); @@ -123,115 +140,54 @@ _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va)  /* Handle cleanup of allocated memory in case of exception */ -#define GETARGS_CAPSULE_NAME_CLEANUP_PTR "getargs.cleanup_ptr" -#define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer" -#define GETARGS_CAPSULE_NAME_CLEANUP_CONVERT "getargs.cleanup_convert" - -static void -cleanup_ptr(PyObject *self) +static int +cleanup_ptr(PyObject *self, void *ptr)  { -    void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR);      if (ptr) {          PyMem_FREE(ptr);      } +    return 0;  } -static void -cleanup_buffer(PyObject *self) +static int +cleanup_buffer(PyObject *self, void *ptr)  { -    Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER); -    if (ptr) { -        PyBuffer_Release(ptr); +    Py_buffer *buf = (Py_buffer *)ptr; +    if (buf) { +        PyBuffer_Release(buf);      } +    return 0;  }  static int -addcleanup(void *ptr, PyObject **freelist, int is_buffer) +addcleanup(void *ptr, freelist_t *freelist, destr_t destructor)  { -    PyObject *cobj; -    const char *name; -    PyCapsule_Destructor destr; - -    if (is_buffer) { -        destr = cleanup_buffer; -        name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; -    } else { -        destr = cleanup_ptr; -        name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; -    } - -    if (!*freelist) { -        *freelist = PyList_New(0); -        if (!*freelist) { -            destr(ptr); -            return -1; -        } -    } +    int index; -    cobj = PyCapsule_New(ptr, name, destr); -    if (!cobj) { -        destr(ptr); -        return -1; -    } -    if (PyList_Append(*freelist, cobj)) { -        Py_DECREF(cobj); -        return -1; -    } -    Py_DECREF(cobj); -    return 0; -} +    index = freelist->first_available; +    freelist->first_available += 1; -static void -cleanup_convert(PyObject *self) -{ -    typedef int (*destr_t)(PyObject *, void *); -    destr_t destr = (destr_t)PyCapsule_GetContext(self); -    void *ptr = PyCapsule_GetPointer(self, -                                     GETARGS_CAPSULE_NAME_CLEANUP_CONVERT); -    if (ptr && destr) -        destr(NULL, ptr); -} +    freelist->entries[index].item = ptr; +    freelist->entries[index].destructor = destructor; -static int -addcleanup_convert(void *ptr, PyObject **freelist, int (*destr)(PyObject*,void*)) -{ -    PyObject *cobj; -    if (!*freelist) { -        *freelist = PyList_New(0); -        if (!*freelist) { -            destr(NULL, ptr); -            return -1; -        } -    } -    cobj = PyCapsule_New(ptr, GETARGS_CAPSULE_NAME_CLEANUP_CONVERT, -                         cleanup_convert); -    if (!cobj) { -        destr(NULL, ptr); -        return -1; -    } -    if (PyCapsule_SetContext(cobj, destr) == -1) { -        /* This really should not happen. */ -        Py_FatalError("capsule refused setting of context."); -    } -    if (PyList_Append(*freelist, cobj)) { -        Py_DECREF(cobj); /* This will also call destr. */ -        return -1; -    } -    Py_DECREF(cobj);      return 0;  }  static int -cleanreturn(int retval, PyObject *freelist) +cleanreturn(int retval, freelist_t *freelist)  { -    if (freelist && retval != 0) { -        /* We were successful, reset the destructors so that they -           don't get called. */ -        Py_ssize_t len = PyList_GET_SIZE(freelist), i; -        for (i = 0; i < len; i++) -            PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL); -    } -    Py_XDECREF(freelist); +    int index; + +    if (retval == 0) { +      /* A failure occurred, therefore execute all of the cleanup +         functions. +      */ +      for (index = 0; index < freelist->first_available; ++index) { +          freelist->entries[index].destructor(NULL, +                                              freelist->entries[index].item); +      } +    } +    PyMem_FREE(freelist->entries);      return retval;  } @@ -250,7 +206,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)      const char *formatsave = format;      Py_ssize_t i, len;      char *msg; -    PyObject *freelist = NULL; +    freelist_t freelist = {0, NULL};      int compat = flags & FLAG_COMPAT;      assert(compat || (args != (PyObject*)NULL)); @@ -306,64 +262,66 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)      format = formatsave; +    freelist.entries = PyMem_NEW(freelistentry_t, max); +    if (freelist.entries == NULL) { +        PyErr_NoMemory(); +        return 0; +    } +      if (compat) {          if (max == 0) {              if (args == NULL)                  return 1; -            PyOS_snprintf(msgbuf, sizeof(msgbuf), -                          "%.200s%s takes no arguments", -                          fname==NULL ? "function" : fname, -                          fname==NULL ? "" : "()"); -            PyErr_SetString(PyExc_TypeError, msgbuf); -            return 0; +            PyErr_Format(PyExc_TypeError, +                         "%.200s%s takes no arguments", +                         fname==NULL ? "function" : fname, +                         fname==NULL ? "" : "()"); +            return cleanreturn(0, &freelist);          }          else if (min == 1 && max == 1) {              if (args == NULL) { -                PyOS_snprintf(msgbuf, sizeof(msgbuf), -                      "%.200s%s takes at least one argument", -                          fname==NULL ? "function" : fname, -                          fname==NULL ? "" : "()"); -                PyErr_SetString(PyExc_TypeError, msgbuf); -                return 0; +                PyErr_Format(PyExc_TypeError, +                             "%.200s%s takes at least one argument", +                             fname==NULL ? "function" : fname, +                             fname==NULL ? "" : "()"); +                return cleanreturn(0, &freelist);              }              msg = convertitem(args, &format, p_va, flags, levels,                                msgbuf, sizeof(msgbuf), &freelist);              if (msg == NULL) -                return cleanreturn(1, freelist); +                return cleanreturn(1, &freelist);              seterror(levels[0], msg, levels+1, fname, message); -            return cleanreturn(0, freelist); +            return cleanreturn(0, &freelist);          }          else {              PyErr_SetString(PyExc_SystemError,                  "old style getargs format uses new features"); -            return 0; +            return cleanreturn(0, &freelist);          }      }      if (!PyTuple_Check(args)) {          PyErr_SetString(PyExc_SystemError,              "new style getargs format but argument is not a tuple"); -        return 0; +        return cleanreturn(0, &freelist);      }      len = PyTuple_GET_SIZE(args);      if (len < min || max < len) { -        if (message == NULL) { -            PyOS_snprintf(msgbuf, sizeof(msgbuf), -                          "%.150s%s takes %s %d argument%s " -                          "(%ld given)", -                          fname==NULL ? "function" : fname, -                          fname==NULL ? "" : "()", -                          min==max ? "exactly" -                          : len < min ? "at least" : "at most", -                          len < min ? min : max, -                          (len < min ? min : max) == 1 ? "" : "s", -                          Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); -            message = msgbuf; -        } -        PyErr_SetString(PyExc_TypeError, message); -        return 0; +        if (message == NULL) +            PyErr_Format(PyExc_TypeError, +                         "%.150s%s takes %s %d argument%s (%ld given)", +                         fname==NULL ? "function" : fname, +                         fname==NULL ? "" : "()", +                         min==max ? "exactly" +                         : len < min ? "at least" : "at most", +                         len < min ? min : max, +                         (len < min ? min : max) == 1 ? "" : "s", +                         Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); +        else +            PyErr_SetString(PyExc_TypeError, message); +        return cleanreturn(0, &freelist);      }      for (i = 0; i < len; i++) { @@ -374,7 +332,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)                            sizeof(msgbuf), &freelist);          if (msg) {              seterror(i+1, msg, levels, fname, msg); -            return cleanreturn(0, freelist); +            return cleanreturn(0, &freelist);          }      } @@ -383,10 +341,10 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)          *format != '|' && *format != ':' && *format != ';') {          PyErr_Format(PyExc_SystemError,                       "bad format string: %.200s", formatsave); -        return cleanreturn(0, freelist); +        return cleanreturn(0, &freelist);      } -    return cleanreturn(1, freelist); +    return cleanreturn(1, &freelist);  } @@ -450,7 +408,7 @@ seterror(int iarg, const char *msg, int *levels, const char *fname,  static char *  converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,               int *levels, char *msgbuf, size_t bufsize, int toplevel, -             PyObject **freelist) +             freelist_t *freelist)  {      int level = 0;      int n = 0; @@ -525,7 +483,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,  static char *  convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, -            int *levels, char *msgbuf, size_t bufsize, PyObject **freelist) +            int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist)  {      char *msg;      const char *format = *p_format; @@ -550,9 +508,6 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, -#define UNICODE_DEFAULT_ENCODING(arg) \ -    _PyUnicode_AsDefaultEncodedString(arg, NULL) -  /* Format an error message generated by convertsimple(). */  static char * @@ -593,7 +548,7 @@ float_argument_error(PyObject *arg)  static char *  convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, -              char *msgbuf, size_t bufsize, PyObject **freelist) +              char *msgbuf, size_t bufsize, freelist_t *freelist)  {      /* For # codes */  #define FETCH_SIZE      int *q=NULL;Py_ssize_t *q2=NULL;\ @@ -615,7 +570,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,      const char *format = *p_format;      char c = *format++; -    PyObject *uarg; +    char *sarg;      switch (c) { @@ -832,6 +787,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,          char *p = va_arg(*p_va, char *);          if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1)              *p = PyBytes_AS_STRING(arg)[0]; +        else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) +            *p = PyByteArray_AS_STRING(arg)[0];          else              return converterr("a byte string of length 1", arg, msgbuf, bufsize);          break; @@ -839,11 +796,33 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,      case 'C': {/* unicode char */          int *p = va_arg(*p_va, int *); -        if (PyUnicode_Check(arg) && -            PyUnicode_GET_SIZE(arg) == 1) -            *p = PyUnicode_AS_UNICODE(arg)[0]; -        else +        int kind; +        void *data; + +        if (!PyUnicode_Check(arg))              return converterr("a unicode character", arg, msgbuf, bufsize); + +        if (PyUnicode_READY(arg)) +            RETURN_ERR_OCCURRED; + +        if (PyUnicode_GET_LENGTH(arg) != 1) +            return converterr("a unicode character", arg, msgbuf, bufsize); + +        kind = PyUnicode_KIND(arg); +        data = PyUnicode_DATA(arg); +        *p = PyUnicode_READ(kind, data, 0); +        break; +    } + +    case 'p': {/* boolean *p*redicate */ +        int *p = va_arg(*p_va, int *); +        int val = PyObject_IsTrue(arg); +        if (val > 0) +            *p = 1; +        else if (val == 0) +            *p = 0; +        else +            RETURN_ERR_OCCURRED;          break;      } @@ -858,7 +837,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,              if (getbuffer(arg, (Py_buffer*)p, &buf) < 0)                  return converterr(buf, arg, msgbuf, bufsize);              format++; -            if (addcleanup(p, freelist, 1)) { +            if (addcleanup(p, freelist, cleanup_buffer)) {                  return converterr(                      "(cleanup problem)",                      arg, msgbuf, bufsize); @@ -891,20 +870,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,              if (c == 'z' && arg == Py_None)                  PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);              else if (PyUnicode_Check(arg)) { -                uarg = UNICODE_DEFAULT_ENCODING(arg); -                if (uarg == NULL) +                Py_ssize_t len; +                sarg = PyUnicode_AsUTF8AndSize(arg, &len); +                if (sarg == NULL)                      return converterr(CONV_UNICODE,                                        arg, msgbuf, bufsize); -                PyBuffer_FillInfo(p, arg, -                                  PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), -                                  1, 0); +                PyBuffer_FillInfo(p, arg, sarg, len, 1, 0);              }              else { /* any buffer-like object */                  char *buf;                  if (getbuffer(arg, p, &buf) < 0)                      return converterr(buf, arg, msgbuf, bufsize);              } -            if (addcleanup(p, freelist, 1)) { +            if (addcleanup(p, freelist, cleanup_buffer)) {                  return converterr(                      "(cleanup problem)",                      arg, msgbuf, bufsize); @@ -920,12 +898,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,                  STORE_SIZE(0);              }              else if (PyUnicode_Check(arg)) { -                uarg = UNICODE_DEFAULT_ENCODING(arg); -                if (uarg == NULL) +                Py_ssize_t len; +                sarg = PyUnicode_AsUTF8AndSize(arg, &len); +                if (sarg == NULL)                      return converterr(CONV_UNICODE,                                        arg, msgbuf, bufsize); -                *p = PyBytes_AS_STRING(uarg); -                STORE_SIZE(PyBytes_GET_SIZE(uarg)); +                *p = sarg; +                STORE_SIZE(len);              }              else { /* any buffer-like object */                  /* XXX Really? */ @@ -939,25 +918,25 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,          } else {              /* "s" or "z" */              char **p = va_arg(*p_va, char **); -            uarg = NULL; +            Py_ssize_t len; +            sarg = NULL;              if (c == 'z' && arg == Py_None)                  *p = NULL;              else if (PyUnicode_Check(arg)) { -                uarg = UNICODE_DEFAULT_ENCODING(arg); -                if (uarg == NULL) +                sarg = PyUnicode_AsUTF8AndSize(arg, &len); +                if (sarg == NULL)                      return converterr(CONV_UNICODE,                                        arg, msgbuf, bufsize); -                *p = PyBytes_AS_STRING(uarg); +                *p = sarg;              }              else                  return converterr(c == 'z' ? "str or None" : "str",                                    arg, msgbuf, bufsize); -            if (*p != NULL && uarg != NULL && -                (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) +            if (*p != NULL && sarg != NULL && (Py_ssize_t) strlen(*p) != len)                  return converterr( -                    c == 'z' ? "str without null bytes or None" -                             : "str without null bytes", +                    c == 'z' ? "str without null characters or None" +                             : "str without null characters",                      arg, msgbuf, bufsize);          }          break; @@ -966,9 +945,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,      case 'u': /* raw unicode buffer (Py_UNICODE *) */      case 'Z': /* raw unicode buffer or None */      { +        Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); +          if (*format == '#') { /* any buffer-like object */              /* "s#" or "Z#" */ -            Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);              FETCH_SIZE;              if (c == 'Z' && arg == Py_None) { @@ -976,23 +956,27 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,                  STORE_SIZE(0);              }              else if (PyUnicode_Check(arg)) { -                *p = PyUnicode_AS_UNICODE(arg); -                STORE_SIZE(PyUnicode_GET_SIZE(arg)); +                Py_ssize_t len; +                *p = PyUnicode_AsUnicodeAndSize(arg, &len); +                if (*p == NULL) +                    RETURN_ERR_OCCURRED; +                STORE_SIZE(len);              }              else                  return converterr("str or None", arg, msgbuf, bufsize);              format++;          } else {              /* "s" or "Z" */ -            Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); -              if (c == 'Z' && arg == Py_None)                  *p = NULL;              else if (PyUnicode_Check(arg)) { -                *p = PyUnicode_AS_UNICODE(arg); -                if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) +                Py_ssize_t len; +                *p = PyUnicode_AsUnicodeAndSize(arg, &len); +                if (*p == NULL) +                    RETURN_ERR_OCCURRED; +                if (Py_UNICODE_strlen(*p) != len)                      return converterr( -                        "str without null character or None", +                        "str without null characters or None",                          arg, msgbuf, bufsize);              } else                  return converterr(c == 'Z' ? "str or None" : "str", @@ -1110,7 +1094,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,                      PyErr_NoMemory();                      RETURN_ERR_OCCURRED;                  } -                if (addcleanup(*buffer, freelist, 0)) { +                if (addcleanup(*buffer, freelist, cleanup_ptr)) {                      Py_DECREF(s);                      return converterr(                          "(cleanup problem)", @@ -1152,7 +1136,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,                  PyErr_NoMemory();                  RETURN_ERR_OCCURRED;              } -            if (addcleanup(*buffer, freelist, 0)) { +            if (addcleanup(*buffer, freelist, cleanup_ptr)) {                  Py_DECREF(s);                  return converterr("(cleanup problem)",                                  arg, msgbuf, bufsize); @@ -1213,7 +1197,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,                  return converterr("(unspecified)",                                    arg, msgbuf, bufsize);              if (res == Py_CLEANUP_SUPPORTED && -                addcleanup_convert(addr, freelist, convert) == -1) +                addcleanup(addr, freelist, convert) == -1)                  return converterr("(cleanup problem)",                                  arg, msgbuf, bufsize);          } @@ -1244,7 +1228,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,              PyBuffer_Release((Py_buffer*)p);              return converterr("contiguous buffer", arg, msgbuf, bufsize);          } -        if (addcleanup(p, freelist, 1)) { +        if (addcleanup(p, freelist, cleanup_buffer)) {              return converterr(                  "(cleanup problem)",                  arg, msgbuf, bufsize); @@ -1431,8 +1415,10 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,      int levels[32];      const char *fname, *msg, *custom_msg, *keyword;      int min = INT_MAX; +    int max = INT_MAX;      int i, len, nargs, nkeywords; -    PyObject *freelist = NULL, *current_arg; +    PyObject *current_arg; +    freelist_t freelist = {0, NULL};      assert(args != NULL && PyTuple_Check(args));      assert(keywords == NULL || PyDict_Check(keywords)); @@ -1456,31 +1442,68 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,      for (len=0; kwlist[len]; len++)          continue; +    freelist.entries = PyMem_NEW(freelistentry_t, len); +    if (freelist.entries == NULL) { +        PyErr_NoMemory(); +        return 0; +    } +      nargs = PyTuple_GET_SIZE(args);      nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords);      if (nargs + nkeywords > len) { -        PyErr_Format(PyExc_TypeError, "%s%s takes at most %d " -                     "argument%s (%d given)", +        PyErr_Format(PyExc_TypeError, +                     "%s%s takes at most %d argument%s (%d given)",                       (fname == NULL) ? "function" : fname,                       (fname == NULL) ? "" : "()",                       len,                       (len == 1) ? "" : "s",                       nargs + nkeywords); -        return 0; +        return cleanreturn(0, &freelist);      }      /* convert tuple args and keyword args in same loop, using kwlist to drive process */      for (i = 0; i < len; i++) {          keyword = kwlist[i];          if (*format == '|') { +            if (min != INT_MAX) { +                PyErr_SetString(PyExc_RuntimeError, +                                "Invalid format string (| specified twice)"); +                return cleanreturn(0, &freelist); +            } +              min = i;              format++; + +            if (max != INT_MAX) { +                PyErr_SetString(PyExc_RuntimeError, +                                "Invalid format string ($ before |)"); +                return cleanreturn(0, &freelist); +            } +        } +        if (*format == '$') { +            if (max != INT_MAX) { +                PyErr_SetString(PyExc_RuntimeError, +                                "Invalid format string ($ specified twice)"); +                return cleanreturn(0, &freelist); +            } + +            max = i; +            format++; + +            if (max < nargs) { +                PyErr_Format(PyExc_TypeError, +                             "Function takes %s %d positional arguments" +                             " (%d given)", +                             (min != INT_MAX) ? "at most" : "exactly", +                             max, nargs); +                return cleanreturn(0, &freelist); +            }          }          if (IS_END_OF_FORMAT(*format)) {              PyErr_Format(PyExc_RuntimeError,                           "More keyword list entries (%d) than "                           "format specifiers (%d)", len, i); -            return cleanreturn(0, freelist); +            return cleanreturn(0, &freelist);          }          current_arg = NULL;          if (nkeywords) { @@ -1494,11 +1517,11 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,                               "Argument given by name ('%s') "                               "and position (%d)",                               keyword, i+1); -                return cleanreturn(0, freelist); +                return cleanreturn(0, &freelist);              }          }          else if (nkeywords && PyErr_Occurred()) -            return cleanreturn(0, freelist); +            return cleanreturn(0, &freelist);          else if (i < nargs)              current_arg = PyTuple_GET_ITEM(args, i); @@ -1507,7 +1530,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,                  levels, msgbuf, sizeof(msgbuf), &freelist);              if (msg) {                  seterror(i+1, msg, levels, fname, custom_msg); -                return cleanreturn(0, freelist); +                return cleanreturn(0, &freelist);              }              continue;          } @@ -1516,14 +1539,14 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,              PyErr_Format(PyExc_TypeError, "Required argument "                           "'%s' (pos %d) not found",                           keyword, i+1); -            return cleanreturn(0, freelist); +            return cleanreturn(0, &freelist);          }          /* current code reports success when all required args           * fulfilled and no keyword args left, with no further           * validation. XXX Maybe skip this in debug build ?           */          if (!nkeywords) -            return cleanreturn(1, freelist); +            return cleanreturn(1, &freelist);          /* We are into optional args, skip thru to any remaining           * keyword args */ @@ -1531,15 +1554,15 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,          if (msg) {              PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg,                           format); -            return cleanreturn(0, freelist); +            return cleanreturn(0, &freelist);          }      } -    if (!IS_END_OF_FORMAT(*format) && *format != '|') { +    if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {          PyErr_Format(PyExc_RuntimeError,              "more argument specifiers than keyword list entries "              "(remaining format:'%s')", format); -        return cleanreturn(0, freelist); +        return cleanreturn(0, &freelist);      }      /* make sure there are no extraneous keyword arguments */ @@ -1552,7 +1575,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,              if (!PyUnicode_Check(key)) {                  PyErr_SetString(PyExc_TypeError,                                  "keywords must be strings"); -                return cleanreturn(0, freelist); +                return cleanreturn(0, &freelist);              }              /* check that _PyUnicode_AsString() result is not NULL */              ks = _PyUnicode_AsString(key); @@ -1569,12 +1592,12 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,                               "'%U' is an invalid keyword "                               "argument for this function",                               key); -                return cleanreturn(0, freelist); +                return cleanreturn(0, &freelist);              }          }      } -    return cleanreturn(1, freelist); +    return cleanreturn(1, &freelist);  } @@ -1586,8 +1609,10 @@ skipitem(const char **p_format, va_list *p_va, int flags)      switch (c) { -    /* simple codes -     * The individual types (second arg of va_arg) are irrelevant */ +    /* +     * codes that take a single data pointer as an argument +     * (the type of the pointer is irrelevant) +     */      case 'b': /* byte -- very short int */      case 'B': /* byte as bitfield */ @@ -1601,22 +1626,21 @@ skipitem(const char **p_format, va_list *p_va, int flags)      case 'L': /* PY_LONG_LONG */      case 'K': /* PY_LONG_LONG sized bitfield */  #endif +    case 'n': /* Py_ssize_t */      case 'f': /* float */      case 'd': /* double */      case 'D': /* complex double */      case 'c': /* char */      case 'C': /* unicode char */ +    case 'p': /* boolean predicate */ +    case 'S': /* string object */ +    case 'Y': /* string object */ +    case 'U': /* unicode string object */          {              (void) va_arg(*p_va, void *);              break;          } -    case 'n': /* Py_ssize_t */ -        { -            (void) va_arg(*p_va, Py_ssize_t *); -            break; -        } -      /* string codes */      case 'e': /* string with encoding */ @@ -1649,16 +1673,6 @@ skipitem(const char **p_format, va_list *p_va, int flags)              break;          } -    /* object codes */ - -    case 'S': /* string object */ -    case 'Y': /* string object */ -    case 'U': /* unicode string object */ -        { -            (void) va_arg(*p_va, PyObject **); -            break; -        } -      case 'O': /* object */          {              if (*format == '!') { | 
