From cd000f04a49d0b51d35ae97bc9c474c5b9d4b29b Mon Sep 17 00:00:00 2001 From: Sean Reifscheider Date: Sat, 1 Aug 2009 23:55:06 +0000 Subject: - Issue #6624: yArg_ParseTuple with "s" format when parsing argument with NUL: Bogus TypeError detail string. --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index a5dc3602b2..486cf7d07d 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -387,7 +387,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg) { - seterror(i+1, msg, levels, fname, message); + seterror(i+1, msg, levels, fname, msg); return cleanreturn(0, freelist); } } -- cgit v1.2.1 From 94be56fe981742b8657e2f07ecb86b5aca70711c Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Sun, 18 Oct 2009 14:25:35 +0000 Subject: Issue 7147 - remove ability to attempt to build Python without complex number support (was broken anyway) --- Python/getargs.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 486cf7d07d..f41cd05eaf 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -818,7 +818,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } -#ifndef WITHOUT_COMPLEX case 'D': {/* complex double */ Py_complex *p = va_arg(*p_va, Py_complex *); Py_complex cval; @@ -829,7 +828,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = cval; break; } -#endif /* WITHOUT_COMPLEX */ case 'c': {/* char */ char *p = va_arg(*p_va, char *); @@ -1772,9 +1770,7 @@ skipitem(const char **p_format, va_list *p_va, int flags) #endif case 'f': /* float */ case 'd': /* double */ -#ifndef WITHOUT_COMPLEX case 'D': /* complex double */ -#endif case 'c': /* char */ { (void) va_arg(*p_va, void *); -- cgit v1.2.1 From 75ca61558705a01811796175088fbf326416257b Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 3 Dec 2009 10:59:46 +0000 Subject: Issue #7414: Add missing 'case 'C'' to skipitem() in getargs.c. This was causing PyArg_ParseTupleAndKeywords(args, kwargs, "|CC", ...) to fail with a RuntimeError. Thanks Case Van Horsen for tracking down the source of this error. --- Python/getargs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index f41cd05eaf..b69aaed56c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1772,6 +1772,7 @@ skipitem(const char **p_format, va_list *p_va, int flags) case 'd': /* double */ case 'D': /* complex double */ case 'c': /* char */ + case 'C': /* unicode char */ { (void) va_arg(*p_va, void *); break; -- cgit v1.2.1 From b663f1e205cdb4abdc00fe7479abe443d9127d83 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Fri, 1 Jan 2010 19:27:32 +0000 Subject: Merged revisions 77218 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r77218 | mark.dickinson | 2010-01-01 17:27:30 +0000 (Fri, 01 Jan 2010) | 5 lines Issue #5080: turn the DeprecationWarning from float arguments passed to integer PyArg_Parse* format codes into a TypeError. Add a DeprecationWarning for floats passed with the 'L' format code, which didn't previously have a warning. ........ --- Python/getargs.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index b69aaed56c..39be98c03f 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -582,6 +582,19 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) #define CONV_UNICODE "(unicode conversion error)" +/* explicitly check for float arguments when integers are expected. For now + * signal a warning. Returns true if an exception was raised. */ +static int +float_argument_warning(PyObject *arg) +{ + if (PyFloat_Check(arg) && + PyErr_Warn(PyExc_DeprecationWarning, + "integer argument expected, got float" )) + return 1; + else + return 0; +} + /* Explicitly check for float arguments when integers are expected. Return 1 for error, 0 if ok. */ static int @@ -777,7 +790,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, #ifdef HAVE_LONG_LONG case 'L': {/* PY_LONG_LONG */ PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); - PY_LONG_LONG ival = PyLong_AsLongLong( arg ); + PY_LONG_LONG ival; + if (float_argument_warning(arg)) + return converterr("long", arg, msgbuf, bufsize); + ival = PyLong_AsLongLong(arg); if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { return converterr("long", arg, msgbuf, bufsize); } else { -- cgit v1.2.1 From fc37f3a644bf3c42ae60b1ce95381a9b2ba0a39d Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 6 Apr 2010 16:01:57 +0000 Subject: Merged revisions 79837 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79837 | antoine.pitrou | 2010-04-06 17:38:25 +0200 (mar., 06 avril 2010) | 19 lines 14 years later, we still don't know what it's for. Spotted by the PyPy developers. Original commit is: branch: trunk user: guido date: Mon Aug 19 21:32:04 1996 +0200 files: Python/getargs.c description: [svn r6499] Support for keyword arguments (PyArg_ParseTupleAndKeywords) donated by Geoff Philbrick (slightly changed by me). Also a little change to make the file acceptable to K&R C compilers (HPUX, SunOS 4.x). ........ --- Python/getargs.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 39be98c03f..17c5317d34 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1849,16 +1849,6 @@ skipitem(const char **p_format, va_list *p_va, int flags) (void) va_arg(*p_va, PyTypeObject*); (void) va_arg(*p_va, PyObject **); } -#if 0 -/* I don't know what this is for */ - else if (*format == '?') { - inquiry pred = va_arg(*p_va, inquiry); - format++; - if ((*pred)(arg)) { - (void) va_arg(*p_va, PyObject **); - } - } -#endif else if (*format == '&') { typedef int (*converter)(PyObject *, void *); (void) va_arg(*p_va, converter); -- cgit v1.2.1 From bb5f3669f8ead9897f824bf97375348d120eb008 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 24 Apr 2010 18:21:17 +0000 Subject: prevent the dict constructor from accepting non-string keyword args #8419 This adds PyArg_ValidateKeywordArguments, which checks that keyword arguments are all strings, using an optimized method if possible. --- Python/getargs.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 17c5317d34..69f5018c4c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1607,6 +1607,21 @@ _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, return retval; } +int +PyArg_ValidateKeywordArguments(PyObject *kwargs) +{ + if (!PyDict_CheckExact(kwargs)) { + PyErr_BadInternalCall(); + return 0; + } + if (!_PyDict_HasOnlyStringKeys(kwargs)) { + PyErr_SetString(PyExc_TypeError, + "keyword arguments must be strings"); + return 0; + } + return 1; +} + #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') static int -- cgit v1.2.1 From 567b94adaaceb622c33f9be1998735dfb95f1707 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 9 May 2010 15:52:27 +0000 Subject: Recorded merge of revisions 81029 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines Untabify C files. Will watch buildbots. ........ --- Python/getargs.c | 3312 +++++++++++++++++++++++++++--------------------------- 1 file changed, 1656 insertions(+), 1656 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 69f5018c4c..4fa2b5bffb 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -14,9 +14,9 @@ int PyArg_ParseTuple(PyObject *, const char *, ...); int PyArg_VaParse(PyObject *, const char *, va_list); int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, ...); + const char *, char **, ...); int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, va_list); + const char *, char **, va_list); #ifdef HAVE_DECLSPEC_DLL /* Export functions */ @@ -40,100 +40,100 @@ 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 **); static char *converttuple(PyObject *, const char **, va_list *, int, - int *, char *, size_t, int, PyObject **); + int *, char *, size_t, int, PyObject **); static char *convertsimple(PyObject *, const char **, va_list *, int, char *, - size_t, PyObject **); + size_t, PyObject **); static Py_ssize_t convertbuffer(PyObject *, void **p, char **); static int getbuffer(PyObject *, Py_buffer *, char**); static int vgetargskeywords(PyObject *, PyObject *, - const char *, char **, va_list *, int); + const char *, char **, va_list *, int); static char *skipitem(const char **, va_list *, int); int PyArg_Parse(PyObject *args, const char *format, ...) { - int retval; - va_list va; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT); - va_end(va); - return retval; + va_start(va, format); + retval = vgetargs1(args, format, &va, FLAG_COMPAT); + va_end(va); + return retval; } int _PyArg_Parse_SizeT(PyObject *args, char *format, ...) { - int retval; - va_list va; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); - va_end(va); - return retval; + va_start(va, format); + retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); + va_end(va); + return retval; } int PyArg_ParseTuple(PyObject *args, const char *format, ...) { - int retval; - va_list va; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, 0); - va_end(va); - return retval; + va_start(va, format); + retval = vgetargs1(args, format, &va, 0); + va_end(va); + return retval; } int _PyArg_ParseTuple_SizeT(PyObject *args, char *format, ...) { - int retval; - va_list va; + int retval; + va_list va; - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_SIZE_T); - va_end(va); - return retval; + va_start(va, format); + retval = vgetargs1(args, format, &va, FLAG_SIZE_T); + va_end(va); + return retval; } int PyArg_VaParse(PyObject *args, const char *format, va_list va) { - va_list lva; + va_list lva; #ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - return vgetargs1(args, format, &lva, 0); + return vgetargs1(args, format, &lva, 0); } int _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) { - va_list lva; + va_list lva; #ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - return vgetargs1(args, format, &lva, FLAG_SIZE_T); + return vgetargs1(args, format, &lva, FLAG_SIZE_T); } @@ -146,261 +146,261 @@ _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) static void cleanup_ptr(PyObject *self) { - void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR); - if (ptr) { - PyMem_FREE(ptr); - } + void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR); + if (ptr) { + PyMem_FREE(ptr); + } } static void cleanup_buffer(PyObject *self) { - Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER); - if (ptr) { - PyBuffer_Release(ptr); - } + Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER); + if (ptr) { + PyBuffer_Release(ptr); + } } static int addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr) { - PyObject *cobj; - const char *name; - - if (!*freelist) { - *freelist = PyList_New(0); - if (!*freelist) { - destr(ptr); - return -1; - } - } - - if (destr == cleanup_ptr) { - name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; - } else if (destr == cleanup_buffer) { - name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; - } else { - return -1; - } - cobj = PyCapsule_New(ptr, name, destr); - if (!cobj) { - destr(ptr); - return -1; - } - if (PyList_Append(*freelist, cobj)) { - Py_DECREF(cobj); - return -1; - } + PyObject *cobj; + const char *name; + + if (!*freelist) { + *freelist = PyList_New(0); + if (!*freelist) { + destr(ptr); + return -1; + } + } + + if (destr == cleanup_ptr) { + name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; + } else if (destr == cleanup_buffer) { + name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; + } else { + return -1; + } + cobj = PyCapsule_New(ptr, name, destr); + if (!cobj) { + destr(ptr); + return -1; + } + if (PyList_Append(*freelist, cobj)) { Py_DECREF(cobj); - return 0; + return -1; + } + Py_DECREF(cobj); + return 0; } 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); + 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); } 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; + 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) { - 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); - return retval; + 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); + return retval; } static int vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) { - char msgbuf[256]; - int levels[32]; - const char *fname = NULL; - const char *message = NULL; - int min = -1; - int max = 0; - int level = 0; - int endfmt = 0; - const char *formatsave = format; - Py_ssize_t i, len; - char *msg; - PyObject *freelist = NULL; - int compat = flags & FLAG_COMPAT; - - assert(compat || (args != (PyObject*)NULL)); - flags = flags & ~FLAG_COMPAT; - - while (endfmt == 0) { - int c = *format++; - switch (c) { - case '(': - if (level == 0) - max++; - level++; - if (level >= 30) - Py_FatalError("too many tuple nesting levels " - "in argument format string"); - break; - case ')': - if (level == 0) - Py_FatalError("excess ')' in getargs format"); - else - level--; - break; - case '\0': - endfmt = 1; - break; - case ':': - fname = format; - endfmt = 1; - break; - case ';': - message = format; - endfmt = 1; - break; - default: - if (level == 0) { - if (c == 'O') - max++; - else if (isalpha(Py_CHARMASK(c))) { - if (c != 'e') /* skip encoded */ - max++; - } else if (c == '|') - min = max; - } - break; - } - } - - if (level != 0) - Py_FatalError(/* '(' */ "missing ')' in getargs format"); - - if (min < 0) - min = max; - - format = formatsave; - - 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; - } - 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; - } - msg = convertitem(args, &format, p_va, flags, levels, - msgbuf, sizeof(msgbuf), &freelist); - if (msg == NULL) - return cleanreturn(1, freelist); - seterror(levels[0], msg, levels+1, fname, message); - return cleanreturn(0, freelist); - } - else { - PyErr_SetString(PyExc_SystemError, - "old style getargs format uses new features"); - return 0; - } - } - - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_SystemError, - "new style getargs format but argument is not a tuple"); - return 0; - } - - 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; - } - - for (i = 0; i < len; i++) { - if (*format == '|') - format++; - msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, - flags, levels, msgbuf, - sizeof(msgbuf), &freelist); - if (msg) { - seterror(i+1, msg, levels, fname, msg); - return cleanreturn(0, freelist); - } - } - - if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) && - *format != '(' && - *format != '|' && *format != ':' && *format != ';') { - PyErr_Format(PyExc_SystemError, - "bad format string: %.200s", formatsave); - return cleanreturn(0, freelist); - } - - return cleanreturn(1, freelist); + char msgbuf[256]; + int levels[32]; + const char *fname = NULL; + const char *message = NULL; + int min = -1; + int max = 0; + int level = 0; + int endfmt = 0; + const char *formatsave = format; + Py_ssize_t i, len; + char *msg; + PyObject *freelist = NULL; + int compat = flags & FLAG_COMPAT; + + assert(compat || (args != (PyObject*)NULL)); + flags = flags & ~FLAG_COMPAT; + + while (endfmt == 0) { + int c = *format++; + switch (c) { + case '(': + if (level == 0) + max++; + level++; + if (level >= 30) + Py_FatalError("too many tuple nesting levels " + "in argument format string"); + break; + case ')': + if (level == 0) + Py_FatalError("excess ')' in getargs format"); + else + level--; + break; + case '\0': + endfmt = 1; + break; + case ':': + fname = format; + endfmt = 1; + break; + case ';': + message = format; + endfmt = 1; + break; + default: + if (level == 0) { + if (c == 'O') + max++; + else if (isalpha(Py_CHARMASK(c))) { + if (c != 'e') /* skip encoded */ + max++; + } else if (c == '|') + min = max; + } + break; + } + } + + if (level != 0) + Py_FatalError(/* '(' */ "missing ')' in getargs format"); + + if (min < 0) + min = max; + + format = formatsave; + + 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; + } + 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; + } + msg = convertitem(args, &format, p_va, flags, levels, + msgbuf, sizeof(msgbuf), &freelist); + if (msg == NULL) + return cleanreturn(1, freelist); + seterror(levels[0], msg, levels+1, fname, message); + return cleanreturn(0, freelist); + } + else { + PyErr_SetString(PyExc_SystemError, + "old style getargs format uses new features"); + return 0; + } + } + + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_SystemError, + "new style getargs format but argument is not a tuple"); + return 0; + } + + 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; + } + + for (i = 0; i < len; i++) { + if (*format == '|') + format++; + msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, + flags, levels, msgbuf, + sizeof(msgbuf), &freelist); + if (msg) { + seterror(i+1, msg, levels, fname, msg); + return cleanreturn(0, freelist); + } + } + + if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) && + *format != '(' && + *format != '|' && *format != ':' && *format != ';') { + PyErr_Format(PyExc_SystemError, + "bad format string: %.200s", formatsave); + return cleanreturn(0, freelist); + } + + return cleanreturn(1, freelist); } @@ -409,37 +409,37 @@ static void seterror(int iarg, const char *msg, int *levels, const char *fname, const char *message) { - char buf[512]; - int i; - char *p = buf; - - if (PyErr_Occurred()) - return; - else if (message == NULL) { - if (fname != NULL) { - PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname); - p += strlen(p); - } - if (iarg != 0) { - PyOS_snprintf(p, sizeof(buf) - (p - buf), - "argument %d", iarg); - i = 0; - p += strlen(p); - while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { - PyOS_snprintf(p, sizeof(buf) - (p - buf), - ", item %d", levels[i]-1); - p += strlen(p); - i++; - } - } - else { - PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument"); - p += strlen(p); - } - PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg); - message = buf; - } - PyErr_SetString(PyExc_TypeError, message); + char buf[512]; + int i; + char *p = buf; + + if (PyErr_Occurred()) + return; + else if (message == NULL) { + if (fname != NULL) { + PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname); + p += strlen(p); + } + if (iarg != 0) { + PyOS_snprintf(p, sizeof(buf) - (p - buf), + "argument %d", iarg); + i = 0; + p += strlen(p); + while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { + PyOS_snprintf(p, sizeof(buf) - (p - buf), + ", item %d", levels[i]-1); + p += strlen(p); + i++; + } + } + else { + PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument"); + p += strlen(p); + } + PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg); + message = buf; + } + PyErr_SetString(PyExc_TypeError, message); } @@ -455,9 +455,9 @@ seterror(int iarg, const char *msg, int *levels, const char *fname, *p_va is undefined, *levels is a 0-terminated list of item numbers, *msgbuf contains an error message, whose format is: - "must be , not ", where: - is the name of the expected type, and - is the name of the actual type, + "must be , not ", where: + is the name of the expected type, and + is the name of the actual type, and msgbuf is returned. */ @@ -466,72 +466,72 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *levels, char *msgbuf, size_t bufsize, int toplevel, PyObject **freelist) { - int level = 0; - int n = 0; - const char *format = *p_format; - int i; - - for (;;) { - int c = *format++; - if (c == '(') { - if (level == 0) - n++; - level++; - } - else if (c == ')') { - if (level == 0) - break; - level--; - } - else if (c == ':' || c == ';' || c == '\0') - break; - else if (level == 0 && isalpha(Py_CHARMASK(c))) - n++; - } - - if (!PySequence_Check(arg) || PyBytes_Check(arg)) { - levels[0] = 0; - PyOS_snprintf(msgbuf, bufsize, - toplevel ? "expected %d arguments, not %.50s" : - "must be %d-item sequence, not %.50s", - n, - arg == Py_None ? "None" : arg->ob_type->tp_name); - return msgbuf; - } - - if ((i = PySequence_Size(arg)) != n) { - levels[0] = 0; - PyOS_snprintf(msgbuf, bufsize, - toplevel ? "expected %d arguments, not %d" : - "must be sequence of length %d, not %d", - n, i); - return msgbuf; - } - - format = *p_format; - for (i = 0; i < n; i++) { - char *msg; - PyObject *item; - item = PySequence_GetItem(arg, i); - if (item == NULL) { - PyErr_Clear(); - levels[0] = i+1; - levels[1] = 0; - strncpy(msgbuf, "is not retrievable", bufsize); - return msgbuf; - } - msg = convertitem(item, &format, p_va, flags, levels+1, - msgbuf, bufsize, freelist); - /* PySequence_GetItem calls tp->sq_item, which INCREFs */ - Py_XDECREF(item); - if (msg != NULL) { - levels[0] = i+1; - return msg; - } - } - - *p_format = format; - return NULL; + int level = 0; + int n = 0; + const char *format = *p_format; + int i; + + for (;;) { + int c = *format++; + if (c == '(') { + if (level == 0) + n++; + level++; + } + else if (c == ')') { + if (level == 0) + break; + level--; + } + else if (c == ':' || c == ';' || c == '\0') + break; + else if (level == 0 && isalpha(Py_CHARMASK(c))) + n++; + } + + if (!PySequence_Check(arg) || PyBytes_Check(arg)) { + levels[0] = 0; + PyOS_snprintf(msgbuf, bufsize, + toplevel ? "expected %d arguments, not %.50s" : + "must be %d-item sequence, not %.50s", + n, + arg == Py_None ? "None" : arg->ob_type->tp_name); + return msgbuf; + } + + if ((i = PySequence_Size(arg)) != n) { + levels[0] = 0; + PyOS_snprintf(msgbuf, bufsize, + toplevel ? "expected %d arguments, not %d" : + "must be sequence of length %d, not %d", + n, i); + return msgbuf; + } + + format = *p_format; + for (i = 0; i < n; i++) { + char *msg; + PyObject *item; + item = PySequence_GetItem(arg, i); + if (item == NULL) { + PyErr_Clear(); + levels[0] = i+1; + levels[1] = 0; + strncpy(msgbuf, "is not retrievable", bufsize); + return msgbuf; + } + msg = convertitem(item, &format, p_va, flags, levels+1, + msgbuf, bufsize, freelist); + /* PySequence_GetItem calls tp->sq_item, which INCREFs */ + Py_XDECREF(item); + if (msg != NULL) { + levels[0] = i+1; + return msg; + } + } + + *p_format = format; + return NULL; } @@ -541,43 +541,43 @@ static char * convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *levels, char *msgbuf, size_t bufsize, PyObject **freelist) { - char *msg; - const char *format = *p_format; - - if (*format == '(' /* ')' */) { - format++; - msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, - bufsize, 0, freelist); - if (msg == NULL) - format++; - } - else { - msg = convertsimple(arg, &format, p_va, flags, - msgbuf, bufsize, freelist); - if (msg != NULL) - levels[0] = 0; - } - if (msg == NULL) - *p_format = format; - return msg; + char *msg; + const char *format = *p_format; + + if (*format == '(' /* ')' */) { + format++; + msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, + bufsize, 0, freelist); + if (msg == NULL) + format++; + } + else { + msg = convertsimple(arg, &format, p_va, flags, + msgbuf, bufsize, freelist); + if (msg != NULL) + levels[0] = 0; + } + if (msg == NULL) + *p_format = format; + return msg; } #define UNICODE_DEFAULT_ENCODING(arg) \ - _PyUnicode_AsDefaultEncodedString(arg, NULL) + _PyUnicode_AsDefaultEncodedString(arg, NULL) /* Format an error message generated by convertsimple(). */ static char * converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) { - assert(expected != NULL); - assert(arg != NULL); - PyOS_snprintf(msgbuf, bufsize, - "must be %.50s, not %.50s", expected, - arg == Py_None ? "None" : arg->ob_type->tp_name); - return msgbuf; + assert(expected != NULL); + assert(arg != NULL); + PyOS_snprintf(msgbuf, bufsize, + "must be %.50s, not %.50s", expected, + arg == Py_None ? "None" : arg->ob_type->tp_name); + return msgbuf; } #define CONV_UNICODE "(unicode conversion error)" @@ -587,12 +587,12 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) static int float_argument_warning(PyObject *arg) { - if (PyFloat_Check(arg) && - PyErr_Warn(PyExc_DeprecationWarning, - "integer argument expected, got float" )) - return 1; - else - return 0; + if (PyFloat_Check(arg) && + PyErr_Warn(PyExc_DeprecationWarning, + "integer argument expected, got float" )) + return 1; + else + return 0; } /* Explicitly check for float arguments when integers are expected. @@ -600,13 +600,13 @@ float_argument_warning(PyObject *arg) static int float_argument_error(PyObject *arg) { - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - return 1; - } - else - return 0; + if (PyFloat_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "integer argument expected, got float" ); + return 1; + } + else + return 0; } /* Convert a non-tuple argument. Return NULL if conversion went OK, @@ -622,837 +622,837 @@ static char * convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *msgbuf, size_t bufsize, PyObject **freelist) { - /* For # codes */ -#define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\ - if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \ - else q=va_arg(*p_va, int*); + /* For # codes */ +#define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\ + if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \ + else q=va_arg(*p_va, int*); #define STORE_SIZE(s) if (flags & FLAG_SIZE_T) *q2=s; else *q=s; #define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) - const char *format = *p_format; - char c = *format++; - PyObject *uarg; - - switch (c) { - - case 'b': { /* unsigned byte -- very short int */ - char *p = va_arg(*p_va, char *); - long ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else if (ival < 0) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else if (ival > UCHAR_MAX) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else - *p = (unsigned char) ival; - break; - } - - case 'B': {/* byte sized bitfield - both signed and unsigned - values allowed */ - char *p = va_arg(*p_va, char *); - long ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = PyLong_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else - *p = (unsigned char) ival; - break; - } - - case 'h': {/* signed short int */ - short *p = va_arg(*p_va, short *); - long ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else - *p = (short) ival; - break; - } - - case 'H': { /* short int sized bitfield, both signed and - unsigned allowed */ - unsigned short *p = va_arg(*p_va, unsigned short *); - long ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = PyLong_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else - *p = (unsigned short) ival; - break; - } - - case 'i': {/* signed int */ - int *p = va_arg(*p_va, int *); - long ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else if (ival > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else if (ival < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); - } - else - *p = ival; - break; - } - - case 'I': { /* int sized bitfield, both signed and - unsigned allowed */ - unsigned int *p = va_arg(*p_va, unsigned int *); - unsigned int ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); - if (ival == (unsigned int)-1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else - *p = ival; - break; - } - - case 'n': /* Py_ssize_t */ - { - PyObject *iobj; - Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); - Py_ssize_t ival = -1; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - iobj = PyNumber_Index(arg); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - *p = ival; - break; - } - case 'l': {/* long int */ - long *p = va_arg(*p_va, long *); - long ival; - if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); - else - *p = ival; - break; - } - - case 'k': { /* long sized bitfield */ - unsigned long *p = va_arg(*p_va, unsigned long *); - unsigned long ival; - if (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongMask(arg); - else - return converterr("integer", arg, msgbuf, bufsize); - *p = ival; - break; - } + const char *format = *p_format; + char c = *format++; + PyObject *uarg; + + switch (c) { + + case 'b': { /* unsigned byte -- very short int */ + char *p = va_arg(*p_va, char *); + long ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else + *p = (unsigned char) ival; + break; + } + + case 'B': {/* byte sized bitfield - both signed and unsigned + values allowed */ + char *p = va_arg(*p_va, char *); + long ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = PyLong_AsUnsignedLongMask(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else + *p = (unsigned char) ival; + break; + } + + case 'h': {/* signed short int */ + short *p = va_arg(*p_va, short *); + long ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else + *p = (short) ival; + break; + } + + case 'H': { /* short int sized bitfield, both signed and + unsigned allowed */ + unsigned short *p = va_arg(*p_va, unsigned short *); + long ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = PyLong_AsUnsignedLongMask(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else + *p = (unsigned short) ival; + break; + } + + case 'i': {/* signed int */ + int *p = va_arg(*p_va, int *); + long ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else if (ival > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed integer is greater than maximum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else if (ival < INT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed integer is less than minimum"); + return converterr("integer", arg, msgbuf, bufsize); + } + else + *p = ival; + break; + } + + case 'I': { /* int sized bitfield, both signed and + unsigned allowed */ + unsigned int *p = va_arg(*p_va, unsigned int *); + unsigned int ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); + if (ival == (unsigned int)-1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else + *p = ival; + break; + } + + case 'n': /* Py_ssize_t */ + { + PyObject *iobj; + Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); + Py_ssize_t ival = -1; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + iobj = PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + *p = ival; + break; + } + case 'l': {/* long int */ + long *p = va_arg(*p_va, long *); + long ival; + if (float_argument_error(arg)) + return converterr("integer", arg, msgbuf, bufsize); + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + return converterr("integer", arg, msgbuf, bufsize); + else + *p = ival; + break; + } + + case 'k': { /* long sized bitfield */ + unsigned long *p = va_arg(*p_va, unsigned long *); + unsigned long ival; + if (PyLong_Check(arg)) + ival = PyLong_AsUnsignedLongMask(arg); + else + return converterr("integer", arg, msgbuf, bufsize); + *p = ival; + break; + } #ifdef HAVE_LONG_LONG - case 'L': {/* PY_LONG_LONG */ - PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); - PY_LONG_LONG ival; - if (float_argument_warning(arg)) - return converterr("long", arg, msgbuf, bufsize); - ival = PyLong_AsLongLong(arg); - if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { - return converterr("long", arg, msgbuf, bufsize); - } else { - *p = ival; - } - break; - } - - case 'K': { /* long long sized bitfield */ - unsigned PY_LONG_LONG *p = va_arg(*p_va, unsigned PY_LONG_LONG *); - unsigned PY_LONG_LONG ival; - if (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongLongMask(arg); - else - return converterr("integer", arg, msgbuf, bufsize); - *p = ival; - break; - } + case 'L': {/* PY_LONG_LONG */ + PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); + PY_LONG_LONG ival; + if (float_argument_warning(arg)) + return converterr("long", arg, msgbuf, bufsize); + ival = PyLong_AsLongLong(arg); + if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { + return converterr("long", arg, msgbuf, bufsize); + } else { + *p = ival; + } + break; + } + + case 'K': { /* long long sized bitfield */ + unsigned PY_LONG_LONG *p = va_arg(*p_va, unsigned PY_LONG_LONG *); + unsigned PY_LONG_LONG ival; + if (PyLong_Check(arg)) + ival = PyLong_AsUnsignedLongLongMask(arg); + else + return converterr("integer", arg, msgbuf, bufsize); + *p = ival; + break; + } #endif - case 'f': {/* float */ - float *p = va_arg(*p_va, float *); - double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) - return converterr("float", arg, msgbuf, bufsize); - else - *p = (float) dval; - break; - } - - case 'd': {/* double */ - double *p = va_arg(*p_va, double *); - double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) - return converterr("float", arg, msgbuf, bufsize); - else - *p = dval; - break; - } - - case 'D': {/* complex double */ - Py_complex *p = va_arg(*p_va, Py_complex *); - Py_complex cval; - cval = PyComplex_AsCComplex(arg); - if (PyErr_Occurred()) - return converterr("complex", arg, msgbuf, bufsize); - else - *p = cval; - break; - } - - case 'c': {/* char */ - char *p = va_arg(*p_va, char *); - if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) - *p = PyBytes_AS_STRING(arg)[0]; - else - return converterr("a byte string of length 1", arg, msgbuf, bufsize); - break; - } - - 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 - return converterr("a unicode character", arg, msgbuf, bufsize); - break; - } - - /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w', 't' codes all - need to be cleaned up! */ - - case 's': {/* text string */ - if (*format == '*') { - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 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, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else if (*format == '#') { - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); - } - else { /* any buffer-like object */ - /* XXX Really? */ - char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - STORE_SIZE(count); - } - format++; - } else { - char **p = va_arg(*p_va, char **); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - } - else - return converterr("string", arg, msgbuf, bufsize); - if ((Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) - return converterr("string without null bytes", - arg, msgbuf, bufsize); - } - break; - } - - case 'y': {/* any buffer-like object, but not PyUnicode */ - void **p = (void **)va_arg(*p_va, char **); - char *buf; - Py_ssize_t count; - if (*format == '*') { - if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - format++; - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - break; - } - count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - else if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; - } - break; - } - - case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ - if (*format == '*') { - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (arg == Py_None) - PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 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, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else if (*format == '#') { /* any buffer-like object */ - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (arg == Py_None) { - *p = 0; - STORE_SIZE(0); - } - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); - } - else { /* any buffer-like object */ - /* XXX Really? */ - char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - STORE_SIZE(count); - } - format++; - } else { - char **p = va_arg(*p_va, char **); - uarg = NULL; - - if (arg == Py_None) - *p = 0; - else if (PyBytes_Check(arg)) { - /* Enable null byte check below */ - uarg = arg; - *p = PyBytes_AS_STRING(arg); - } - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - } - else - return converterr("string or None", - arg, msgbuf, bufsize); - if (*format == '#') { - FETCH_SIZE; - assert(0); /* XXX redundant with if-case */ - if (arg == Py_None) { - STORE_SIZE(0); - } - else { - STORE_SIZE(PyBytes_Size(arg)); - } - format++; - } - else if (*p != NULL && uarg != NULL && - (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) - return converterr( - "string without null bytes or None", - arg, msgbuf, bufsize); - } - break; - } - - case 'Z': {/* unicode, may be NULL (None) */ - if (*format == '#') { /* any buffer-like object */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - FETCH_SIZE; - - if (arg == Py_None) { - *p = 0; - STORE_SIZE(0); - } - else if (PyUnicode_Check(arg)) { - *p = PyUnicode_AS_UNICODE(arg); - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - } - format++; - } else { - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - - if (arg == Py_None) - *p = 0; - else if (PyUnicode_Check(arg)) - *p = PyUnicode_AS_UNICODE(arg); - else - return converterr("string or None", - arg, msgbuf, bufsize); - } - break; - } - - case 'e': {/* encoded string */ - char **buffer; - const char *encoding; - PyObject *s; - int recode_strings; - Py_ssize_t size; - const char *ptr; - - /* Get 'e' parameter: the encoding name */ - encoding = (const char *)va_arg(*p_va, const char *); - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Get output buffer parameter: - 's' (recode all objects via Unicode) or - 't' (only recode non-string objects) - */ - if (*format == 's') - recode_strings = 1; - else if (*format == 't') - recode_strings = 0; - else - return converterr( - "(unknown parser marker combination)", - arg, msgbuf, bufsize); - buffer = (char **)va_arg(*p_va, char **); - format++; - if (buffer == NULL) - return converterr("(buffer is NULL)", - arg, msgbuf, bufsize); - - /* Encode object */ - if (!recode_strings && - (PyBytes_Check(arg) || PyByteArray_Check(arg))) { - s = arg; - Py_INCREF(s); - if (PyObject_AsCharBuffer(s, &ptr, &size) < 0) - return converterr("(AsCharBuffer failed)", - arg, msgbuf, bufsize); - } - else { - PyObject *u; - - /* Convert object to Unicode */ - u = PyUnicode_FromObject(arg); - if (u == NULL) - return converterr( - "string or unicode or text buffer", - arg, msgbuf, bufsize); - - /* Encode object; use default error handling */ - s = PyUnicode_AsEncodedString(u, - encoding, - NULL); - Py_DECREF(u); - if (s == NULL) - return converterr("(encoding failed)", - arg, msgbuf, bufsize); - if (!PyBytes_Check(s)) { - Py_DECREF(s); - return converterr( - "(encoder failed to return bytes)", - arg, msgbuf, bufsize); - } - size = PyBytes_GET_SIZE(s); - ptr = PyBytes_AS_STRING(s); - if (ptr == NULL) - ptr = ""; - } - - /* Write output; output is guaranteed to be 0-terminated */ - if (*format == '#') { - /* Using buffer length parameter '#': - - - if *buffer is NULL, a new buffer of the - needed size is allocated and the data - copied into it; *buffer is updated to point - to the new buffer; the caller is - responsible for PyMem_Free()ing it after - usage - - - if *buffer is not NULL, the data is - copied to *buffer; *buffer_len has to be - set to the size of the buffer on input; - buffer overflow is signalled with an error; - buffer has to provide enough room for the - encoded string plus the trailing 0-byte - - - in both cases, *buffer_len is updated to - the size of the buffer /excluding/ the - trailing 0-byte - - */ - FETCH_SIZE; - - format++; - if (q == NULL && q2 == NULL) { - Py_DECREF(s); - return converterr( - "(buffer_len is NULL)", - arg, msgbuf, bufsize); - } - if (*buffer == NULL) { - *buffer = PyMem_NEW(char, size + 1); - if (*buffer == NULL) { - Py_DECREF(s); - return converterr( - "(memory error)", - arg, msgbuf, bufsize); - } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { - Py_DECREF(s); - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - } else { - if (size + 1 > BUFFER_LEN) { - Py_DECREF(s); - return converterr( - "(buffer overflow)", - arg, msgbuf, bufsize); - } - } - memcpy(*buffer, ptr, size+1); - STORE_SIZE(size); - } else { - /* Using a 0-terminated buffer: - - - the encoded string has to be 0-terminated - for this variant to work; if it is not, an - error raised - - - a new buffer of the needed size is - allocated and the data copied into it; - *buffer is updated to point to the new - buffer; the caller is responsible for - PyMem_Free()ing it after usage - - */ - if ((Py_ssize_t)strlen(ptr) != size) { - Py_DECREF(s); - return converterr( - "encoded string without NULL bytes", - arg, msgbuf, bufsize); - } - *buffer = PyMem_NEW(char, size + 1); - if (*buffer == NULL) { - Py_DECREF(s); - return converterr("(memory error)", - arg, msgbuf, bufsize); - } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { - Py_DECREF(s); - return converterr("(cleanup problem)", - arg, msgbuf, bufsize); - } - memcpy(*buffer, ptr, size+1); - } - Py_DECREF(s); - break; - } - - case 'u': {/* raw unicode buffer (Py_UNICODE *) */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (!PyUnicode_Check(arg)) - return converterr("str", arg, msgbuf, bufsize); - *p = PyUnicode_AS_UNICODE(arg); - if (*format == '#') { /* store pointer and size */ - FETCH_SIZE; - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - format++; - } - break; - } - - case 'S': { /* PyBytes object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyBytes_Check(arg)) - *p = arg; - else - return converterr("bytes", arg, msgbuf, bufsize); - break; - } - - case 'Y': { /* PyByteArray object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyByteArray_Check(arg)) - *p = arg; - else - return converterr("buffer", arg, msgbuf, bufsize); - break; - } - - case 'U': { /* PyUnicode object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyUnicode_Check(arg)) - *p = arg; - else - return converterr("str", arg, msgbuf, bufsize); - break; - } - - case 'O': { /* object */ - PyTypeObject *type; - PyObject **p; - if (*format == '!') { - type = va_arg(*p_va, PyTypeObject*); - p = va_arg(*p_va, PyObject **); - format++; - if (PyType_IsSubtype(arg->ob_type, type)) - *p = arg; - else - return converterr(type->tp_name, arg, msgbuf, bufsize); - - } - else if (*format == '?') { - inquiry pred = va_arg(*p_va, inquiry); - p = va_arg(*p_va, PyObject **); - format++; - if ((*pred)(arg)) - *p = arg; - else - return converterr("(unspecified)", - arg, msgbuf, bufsize); - - } - else if (*format == '&') { - typedef int (*converter)(PyObject *, void *); - converter convert = va_arg(*p_va, converter); - void *addr = va_arg(*p_va, void *); - int res; - format++; - if (! (res = (*convert)(arg, addr))) - return converterr("(unspecified)", - arg, msgbuf, bufsize); - if (res == Py_CLEANUP_SUPPORTED && - addcleanup_convert(addr, freelist, convert) == -1) - return converterr("(cleanup problem)", - arg, msgbuf, bufsize); - } - else { - p = va_arg(*p_va, PyObject **); - *p = arg; - } - break; - } - - - case 'w': { /* memory buffer, read-write access */ - void **p = va_arg(*p_va, void **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - int temp=-1; - Py_buffer view; - - if (pb && pb->bf_releasebuffer && *format != '*') - /* Buffer must be released, yet caller does not use - the Py_buffer protocol. */ - return converterr("pinned buffer", arg, msgbuf, bufsize); - - - if (pb && pb->bf_getbuffer && *format == '*') { - /* Caller is interested in Py_buffer, and the object - supports it directly. */ - format++; - if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); - return converterr("read-write buffer", arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) - return converterr("contiguous buffer", arg, msgbuf, bufsize); - break; - } - - /* Here we have processed w*, only w and w# remain. */ - if (pb == NULL || - pb->bf_getbuffer == NULL || - ((temp = PyObject_GetBuffer(arg, &view, - PyBUF_SIMPLE)) != 0) || - view.readonly == 1) { - if (temp==0) { - PyBuffer_Release(&view); - } - return converterr("single-segment read-write buffer", - arg, msgbuf, bufsize); + case 'f': {/* float */ + float *p = va_arg(*p_va, float *); + double dval = PyFloat_AsDouble(arg); + if (PyErr_Occurred()) + return converterr("float", arg, msgbuf, bufsize); + else + *p = (float) dval; + break; + } + + case 'd': {/* double */ + double *p = va_arg(*p_va, double *); + double dval = PyFloat_AsDouble(arg); + if (PyErr_Occurred()) + return converterr("float", arg, msgbuf, bufsize); + else + *p = dval; + break; + } + + case 'D': {/* complex double */ + Py_complex *p = va_arg(*p_va, Py_complex *); + Py_complex cval; + cval = PyComplex_AsCComplex(arg); + if (PyErr_Occurred()) + return converterr("complex", arg, msgbuf, bufsize); + else + *p = cval; + break; + } + + case 'c': {/* char */ + char *p = va_arg(*p_va, char *); + if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) + *p = PyBytes_AS_STRING(arg)[0]; + else + return converterr("a byte string of length 1", arg, msgbuf, bufsize); + break; + } + + 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 + return converterr("a unicode character", arg, msgbuf, bufsize); + break; + } + + /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w', 't' codes all + need to be cleaned up! */ + + case 's': {/* text string */ + if (*format == '*') { + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, + PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), + 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, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + format++; + } else if (*format == '#') { + void **p = (void **)va_arg(*p_va, char **); + FETCH_SIZE; + + if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + STORE_SIZE(PyBytes_GET_SIZE(uarg)); + } + else { /* any buffer-like object */ + /* XXX Really? */ + char *buf; + Py_ssize_t count = convertbuffer(arg, p, &buf); + if (count < 0) + return converterr(buf, arg, msgbuf, bufsize); + STORE_SIZE(count); + } + format++; + } else { + char **p = va_arg(*p_va, char **); + + if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + } + else + return converterr("string", arg, msgbuf, bufsize); + if ((Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) + return converterr("string without null bytes", + arg, msgbuf, bufsize); + } + break; + } + + case 'y': {/* any buffer-like object, but not PyUnicode */ + void **p = (void **)va_arg(*p_va, char **); + char *buf; + Py_ssize_t count; + if (*format == '*') { + if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + format++; + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + break; + } + count = convertbuffer(arg, p, &buf); + if (count < 0) + return converterr(buf, arg, msgbuf, bufsize); + else if (*format == '#') { + FETCH_SIZE; + STORE_SIZE(count); + format++; + } + break; + } + + case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ + if (*format == '*') { + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (arg == Py_None) + PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, + PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), + 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, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + format++; + } else if (*format == '#') { /* any buffer-like object */ + void **p = (void **)va_arg(*p_va, char **); + FETCH_SIZE; + + if (arg == Py_None) { + *p = 0; + STORE_SIZE(0); + } + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + STORE_SIZE(PyBytes_GET_SIZE(uarg)); + } + else { /* any buffer-like object */ + /* XXX Really? */ + char *buf; + Py_ssize_t count = convertbuffer(arg, p, &buf); + if (count < 0) + return converterr(buf, arg, msgbuf, bufsize); + STORE_SIZE(count); + } + format++; + } else { + char **p = va_arg(*p_va, char **); + uarg = NULL; + + if (arg == Py_None) + *p = 0; + else if (PyBytes_Check(arg)) { + /* Enable null byte check below */ + uarg = arg; + *p = PyBytes_AS_STRING(arg); + } + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyBytes_AS_STRING(uarg); + } + else + return converterr("string or None", + arg, msgbuf, bufsize); + if (*format == '#') { + FETCH_SIZE; + assert(0); /* XXX redundant with if-case */ + if (arg == Py_None) { + STORE_SIZE(0); + } + else { + STORE_SIZE(PyBytes_Size(arg)); + } + format++; + } + else if (*p != NULL && uarg != NULL && + (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) + return converterr( + "string without null bytes or None", + arg, msgbuf, bufsize); + } + break; + } + + case 'Z': {/* unicode, may be NULL (None) */ + if (*format == '#') { /* any buffer-like object */ + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + FETCH_SIZE; + + if (arg == Py_None) { + *p = 0; + STORE_SIZE(0); + } + else if (PyUnicode_Check(arg)) { + *p = PyUnicode_AS_UNICODE(arg); + STORE_SIZE(PyUnicode_GET_SIZE(arg)); + } + format++; + } else { + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + + if (arg == Py_None) + *p = 0; + else if (PyUnicode_Check(arg)) + *p = PyUnicode_AS_UNICODE(arg); + else + return converterr("string or None", + arg, msgbuf, bufsize); + } + break; + } + + case 'e': {/* encoded string */ + char **buffer; + const char *encoding; + PyObject *s; + int recode_strings; + Py_ssize_t size; + const char *ptr; + + /* Get 'e' parameter: the encoding name */ + encoding = (const char *)va_arg(*p_va, const char *); + if (encoding == NULL) + encoding = PyUnicode_GetDefaultEncoding(); + + /* Get output buffer parameter: + 's' (recode all objects via Unicode) or + 't' (only recode non-string objects) + */ + if (*format == 's') + recode_strings = 1; + else if (*format == 't') + recode_strings = 0; + else + return converterr( + "(unknown parser marker combination)", + arg, msgbuf, bufsize); + buffer = (char **)va_arg(*p_va, char **); + format++; + if (buffer == NULL) + return converterr("(buffer is NULL)", + arg, msgbuf, bufsize); + + /* Encode object */ + if (!recode_strings && + (PyBytes_Check(arg) || PyByteArray_Check(arg))) { + s = arg; + Py_INCREF(s); + if (PyObject_AsCharBuffer(s, &ptr, &size) < 0) + return converterr("(AsCharBuffer failed)", + arg, msgbuf, bufsize); + } + else { + PyObject *u; + + /* Convert object to Unicode */ + u = PyUnicode_FromObject(arg); + if (u == NULL) + return converterr( + "string or unicode or text buffer", + arg, msgbuf, bufsize); + + /* Encode object; use default error handling */ + s = PyUnicode_AsEncodedString(u, + encoding, + NULL); + Py_DECREF(u); + if (s == NULL) + return converterr("(encoding failed)", + arg, msgbuf, bufsize); + if (!PyBytes_Check(s)) { + Py_DECREF(s); + return converterr( + "(encoder failed to return bytes)", + arg, msgbuf, bufsize); + } + size = PyBytes_GET_SIZE(s); + ptr = PyBytes_AS_STRING(s); + if (ptr == NULL) + ptr = ""; + } + + /* Write output; output is guaranteed to be 0-terminated */ + if (*format == '#') { + /* Using buffer length parameter '#': + + - if *buffer is NULL, a new buffer of the + needed size is allocated and the data + copied into it; *buffer is updated to point + to the new buffer; the caller is + responsible for PyMem_Free()ing it after + usage + + - if *buffer is not NULL, the data is + copied to *buffer; *buffer_len has to be + set to the size of the buffer on input; + buffer overflow is signalled with an error; + buffer has to provide enough room for the + encoded string plus the trailing 0-byte + + - in both cases, *buffer_len is updated to + the size of the buffer /excluding/ the + trailing 0-byte + + */ + FETCH_SIZE; + + format++; + if (q == NULL && q2 == NULL) { + Py_DECREF(s); + return converterr( + "(buffer_len is NULL)", + arg, msgbuf, bufsize); + } + if (*buffer == NULL) { + *buffer = PyMem_NEW(char, size + 1); + if (*buffer == NULL) { + Py_DECREF(s); + return converterr( + "(memory error)", + arg, msgbuf, bufsize); } + if (addcleanup(*buffer, freelist, cleanup_ptr)) { + Py_DECREF(s); + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + } else { + if (size + 1 > BUFFER_LEN) { + Py_DECREF(s); + return converterr( + "(buffer overflow)", + arg, msgbuf, bufsize); + } + } + memcpy(*buffer, ptr, size+1); + STORE_SIZE(size); + } else { + /* Using a 0-terminated buffer: + + - the encoded string has to be 0-terminated + for this variant to work; if it is not, an + error raised + + - a new buffer of the needed size is + allocated and the data copied into it; + *buffer is updated to point to the new + buffer; the caller is responsible for + PyMem_Free()ing it after usage + + */ + if ((Py_ssize_t)strlen(ptr) != size) { + Py_DECREF(s); + return converterr( + "encoded string without NULL bytes", + arg, msgbuf, bufsize); + } + *buffer = PyMem_NEW(char, size + 1); + if (*buffer == NULL) { + Py_DECREF(s); + return converterr("(memory error)", + arg, msgbuf, bufsize); + } + if (addcleanup(*buffer, freelist, cleanup_ptr)) { + Py_DECREF(s); + return converterr("(cleanup problem)", + arg, msgbuf, bufsize); + } + memcpy(*buffer, ptr, size+1); + } + Py_DECREF(s); + break; + } + + case 'u': {/* raw unicode buffer (Py_UNICODE *) */ + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + if (!PyUnicode_Check(arg)) + return converterr("str", arg, msgbuf, bufsize); + *p = PyUnicode_AS_UNICODE(arg); + if (*format == '#') { /* store pointer and size */ + FETCH_SIZE; + STORE_SIZE(PyUnicode_GET_SIZE(arg)); + format++; + } + break; + } + + case 'S': { /* PyBytes object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyBytes_Check(arg)) + *p = arg; + else + return converterr("bytes", arg, msgbuf, bufsize); + break; + } + + case 'Y': { /* PyByteArray object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyByteArray_Check(arg)) + *p = arg; + else + return converterr("buffer", arg, msgbuf, bufsize); + break; + } + + case 'U': { /* PyUnicode object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyUnicode_Check(arg)) + *p = arg; + else + return converterr("str", arg, msgbuf, bufsize); + break; + } + + case 'O': { /* object */ + PyTypeObject *type; + PyObject **p; + if (*format == '!') { + type = va_arg(*p_va, PyTypeObject*); + p = va_arg(*p_va, PyObject **); + format++; + if (PyType_IsSubtype(arg->ob_type, type)) + *p = arg; + else + return converterr(type->tp_name, arg, msgbuf, bufsize); + + } + else if (*format == '?') { + inquiry pred = va_arg(*p_va, inquiry); + p = va_arg(*p_va, PyObject **); + format++; + if ((*pred)(arg)) + *p = arg; + else + return converterr("(unspecified)", + arg, msgbuf, bufsize); + + } + else if (*format == '&') { + typedef int (*converter)(PyObject *, void *); + converter convert = va_arg(*p_va, converter); + void *addr = va_arg(*p_va, void *); + int res; + format++; + if (! (res = (*convert)(arg, addr))) + return converterr("(unspecified)", + arg, msgbuf, bufsize); + if (res == Py_CLEANUP_SUPPORTED && + addcleanup_convert(addr, freelist, convert) == -1) + return converterr("(cleanup problem)", + arg, msgbuf, bufsize); + } + else { + p = va_arg(*p_va, PyObject **); + *p = arg; + } + break; + } + + + case 'w': { /* memory buffer, read-write access */ + void **p = va_arg(*p_va, void **); + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + Py_ssize_t count; + int temp=-1; + Py_buffer view; - if ((count = view.len) < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - *p = view.buf; - if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; - } - break; - } - - /*TEO: This can be eliminated --- here only for backward - compatibility */ - case 't': { /* 8-bit character buffer, read-only access */ - char **p = va_arg(*p_va, char **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - Py_buffer view; - - if (*format++ != '#') - return converterr( - "invalid use of 't' format character", - arg, msgbuf, bufsize); - if (pb == NULL || pb->bf_getbuffer == NULL) - return converterr( - "bytes or read-only character buffer", - arg, msgbuf, bufsize); - - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) - return converterr("string or single-segment read-only buffer", - arg, msgbuf, bufsize); - - count = view.len; - *p = view.buf; - if (pb->bf_releasebuffer) - return converterr( - "string or pinned buffer", - arg, msgbuf, bufsize); - - PyBuffer_Release(&view); - - if (count < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - { - FETCH_SIZE; - STORE_SIZE(count); - } - break; - } - - default: - return converterr("impossible", arg, msgbuf, bufsize); - - } - - *p_format = format; - return NULL; + if (pb && pb->bf_releasebuffer && *format != '*') + /* Buffer must be released, yet caller does not use + the Py_buffer protocol. */ + return converterr("pinned buffer", arg, msgbuf, bufsize); + + + if (pb && pb->bf_getbuffer && *format == '*') { + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + format++; + if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write buffer", arg, msgbuf, bufsize); + } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) + return converterr("contiguous buffer", arg, msgbuf, bufsize); + break; + } + + /* Here we have processed w*, only w and w# remain. */ + if (pb == NULL || + pb->bf_getbuffer == NULL || + ((temp = PyObject_GetBuffer(arg, &view, + PyBUF_SIMPLE)) != 0) || + view.readonly == 1) { + if (temp==0) { + PyBuffer_Release(&view); + } + return converterr("single-segment read-write buffer", + arg, msgbuf, bufsize); + } + + if ((count = view.len) < 0) + return converterr("(unspecified)", arg, msgbuf, bufsize); + *p = view.buf; + if (*format == '#') { + FETCH_SIZE; + STORE_SIZE(count); + format++; + } + break; + } + + /*TEO: This can be eliminated --- here only for backward + compatibility */ + case 't': { /* 8-bit character buffer, read-only access */ + char **p = va_arg(*p_va, char **); + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + Py_ssize_t count; + Py_buffer view; + + if (*format++ != '#') + return converterr( + "invalid use of 't' format character", + arg, msgbuf, bufsize); + if (pb == NULL || pb->bf_getbuffer == NULL) + return converterr( + "bytes or read-only character buffer", + arg, msgbuf, bufsize); + + if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) + return converterr("string or single-segment read-only buffer", + arg, msgbuf, bufsize); + + count = view.len; + *p = view.buf; + if (pb->bf_releasebuffer) + return converterr( + "string or pinned buffer", + arg, msgbuf, bufsize); + + PyBuffer_Release(&view); + + if (count < 0) + return converterr("(unspecified)", arg, msgbuf, bufsize); + { + FETCH_SIZE; + STORE_SIZE(count); + } + break; + } + + default: + return converterr("impossible", arg, msgbuf, bufsize); + + } + + *p_format = format; + return NULL; } static Py_ssize_t convertbuffer(PyObject *arg, void **p, char **errmsg) { - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - Py_buffer view; - - *errmsg = NULL; - *p = NULL; - if (pb == NULL || - pb->bf_getbuffer == NULL || - pb->bf_releasebuffer != NULL) { - *errmsg = "bytes or read-only buffer"; - return -1; - } - - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) { - *errmsg = "bytes or single-segment read-only buffer"; - return -1; - } - count = view.len; - *p = view.buf; - PyBuffer_Release(&view); - return count; + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + Py_ssize_t count; + Py_buffer view; + + *errmsg = NULL; + *p = NULL; + if (pb == NULL || + pb->bf_getbuffer == NULL || + pb->bf_releasebuffer != NULL) { + *errmsg = "bytes or read-only buffer"; + return -1; + } + + if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) { + *errmsg = "bytes or single-segment read-only buffer"; + return -1; + } + count = view.len; + *p = view.buf; + PyBuffer_Release(&view); + return count; } /* XXX for 3.x, getbuffer and convertbuffer can probably @@ -1460,32 +1460,32 @@ convertbuffer(PyObject *arg, void **p, char **errmsg) static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - void *buf; - Py_ssize_t count; - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - if (pb == NULL) { - *errmsg = "bytes or buffer"; - return -1; - } - if (pb->bf_getbuffer) { - if (PyObject_GetBuffer(arg, view, 0) < 0) { - *errmsg = "convertible to a buffer"; - return -1; - } - if (!PyBuffer_IsContiguous(view, 'C')) { - *errmsg = "contiguous buffer"; - return -1; - } - return 0; - } - - count = convertbuffer(arg, &buf, errmsg); - if (count < 0) { - *errmsg = "convertible to a buffer"; - return count; - } - PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); - return 0; + void *buf; + Py_ssize_t count; + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + if (pb == NULL) { + *errmsg = "bytes or buffer"; + return -1; + } + if (pb->bf_getbuffer) { + if (PyObject_GetBuffer(arg, view, 0) < 0) { + *errmsg = "convertible to a buffer"; + return -1; + } + if (!PyBuffer_IsContiguous(view, 'C')) { + *errmsg = "contiguous buffer"; + return -1; + } + return 0; + } + + count = convertbuffer(arg, &buf, errmsg); + if (count < 0) { + *errmsg = "convertible to a buffer"; + return count; + } + PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); + return 0; } /* Support for keyword arguments donated by @@ -1494,51 +1494,51 @@ getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) /* Return false (0) for error, else true. */ int PyArg_ParseTupleAndKeywords(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, ...) + PyObject *keywords, + const char *format, + char **kwlist, ...) { - int retval; - va_list va; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_start(va, kwlist); - retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0); - va_end(va); - return retval; + int retval; + va_list va; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_start(va, kwlist); + retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0); + va_end(va); + return retval; } int _PyArg_ParseTupleAndKeywords_SizeT(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, ...) + PyObject *keywords, + const char *format, + char **kwlist, ...) { - int retval; - va_list va; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_start(va, kwlist); - retval = vgetargskeywords(args, keywords, format, - kwlist, &va, FLAG_SIZE_T); - va_end(va); - return retval; + int retval; + va_list va; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_start(va, kwlist); + retval = vgetargskeywords(args, keywords, format, + kwlist, &va, FLAG_SIZE_T); + va_end(va); + return retval; } @@ -1548,422 +1548,422 @@ PyArg_VaParseTupleAndKeywords(PyObject *args, const char *format, char **kwlist, va_list va) { - int retval; - va_list lva; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } + int retval; + va_list lva; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } #ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); - return retval; + retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); + return retval; } int _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, va_list va) + PyObject *keywords, + const char *format, + char **kwlist, va_list va) { - int retval; - va_list lva; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } + int retval; + va_list lva; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } #ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); + memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy - __va_copy(lva, va); + __va_copy(lva, va); #else - lva = va; + lva = va; #endif #endif - retval = vgetargskeywords(args, keywords, format, - kwlist, &lva, FLAG_SIZE_T); - return retval; + retval = vgetargskeywords(args, keywords, format, + kwlist, &lva, FLAG_SIZE_T); + return retval; } int PyArg_ValidateKeywordArguments(PyObject *kwargs) { - if (!PyDict_CheckExact(kwargs)) { - PyErr_BadInternalCall(); - return 0; - } - if (!_PyDict_HasOnlyStringKeys(kwargs)) { - PyErr_SetString(PyExc_TypeError, - "keyword arguments must be strings"); - return 0; - } - return 1; + if (!PyDict_CheckExact(kwargs)) { + PyErr_BadInternalCall(); + return 0; + } + if (!_PyDict_HasOnlyStringKeys(kwargs)) { + PyErr_SetString(PyExc_TypeError, + "keyword arguments must be strings"); + return 0; + } + return 1; } #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') static int vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, - char **kwlist, va_list *p_va, int flags) + char **kwlist, va_list *p_va, int flags) { - char msgbuf[512]; - int levels[32]; - const char *fname, *msg, *custom_msg, *keyword; - int min = INT_MAX; - int i, len, nargs, nkeywords; - PyObject *freelist = NULL, *current_arg; - - assert(args != NULL && PyTuple_Check(args)); - assert(keywords == NULL || PyDict_Check(keywords)); - assert(format != NULL); - assert(kwlist != NULL); - assert(p_va != NULL); - - /* grab the function name or custom error msg first (mutually exclusive) */ - fname = strchr(format, ':'); - if (fname) { - fname++; - custom_msg = NULL; - } - else { - custom_msg = strchr(format,';'); - if (custom_msg) - custom_msg++; - } - - /* scan kwlist and get greatest possible nbr of args */ - for (len=0; kwlist[len]; len++) - continue; - - 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)", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()", - len, - (len == 1) ? "" : "s", - nargs + nkeywords); - return 0; - } - - /* 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 == '|') { - min = i; - format++; - } - 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); - } - current_arg = NULL; - if (nkeywords) { - current_arg = PyDict_GetItemString(keywords, keyword); - } - if (current_arg) { - --nkeywords; - if (i < nargs) { - /* arg present in tuple and in dict */ - PyErr_Format(PyExc_TypeError, - "Argument given by name ('%s') " - "and position (%d)", - keyword, i+1); - return cleanreturn(0, freelist); - } - } - else if (nkeywords && PyErr_Occurred()) - return cleanreturn(0, freelist); - else if (i < nargs) - current_arg = PyTuple_GET_ITEM(args, i); - - if (current_arg) { - msg = convertitem(current_arg, &format, p_va, flags, - levels, msgbuf, sizeof(msgbuf), &freelist); - if (msg) { - seterror(i+1, msg, levels, fname, custom_msg); - return cleanreturn(0, freelist); - } - continue; - } - - if (i < min) { - PyErr_Format(PyExc_TypeError, "Required argument " - "'%s' (pos %d) not found", - keyword, i+1); - 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); - - /* We are into optional args, skip thru to any remaining - * keyword args */ - msg = skipitem(&format, p_va, flags); - if (msg) { - PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg, - format); - return cleanreturn(0, freelist); - } - } - - if (!IS_END_OF_FORMAT(*format) && *format != '|') { - PyErr_Format(PyExc_RuntimeError, - "more argument specifiers than keyword list entries " - "(remaining format:'%s')", format); - return cleanreturn(0, freelist); - } - - /* make sure there are no extraneous keyword arguments */ - if (nkeywords > 0) { - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(keywords, &pos, &key, &value)) { - int match = 0; - char *ks; - if (!PyUnicode_Check(key)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return cleanreturn(0, freelist); - } - ks = _PyUnicode_AsString(key); - for (i = 0; i < len; i++) { - if (!strcmp(ks, kwlist[i])) { - match = 1; - break; - } - } - if (!match) { - PyErr_Format(PyExc_TypeError, - "'%s' is an invalid keyword " - "argument for this function", - ks); - return cleanreturn(0, freelist); - } - } - } - - return cleanreturn(1, freelist); + char msgbuf[512]; + int levels[32]; + const char *fname, *msg, *custom_msg, *keyword; + int min = INT_MAX; + int i, len, nargs, nkeywords; + PyObject *freelist = NULL, *current_arg; + + assert(args != NULL && PyTuple_Check(args)); + assert(keywords == NULL || PyDict_Check(keywords)); + assert(format != NULL); + assert(kwlist != NULL); + assert(p_va != NULL); + + /* grab the function name or custom error msg first (mutually exclusive) */ + fname = strchr(format, ':'); + if (fname) { + fname++; + custom_msg = NULL; + } + else { + custom_msg = strchr(format,';'); + if (custom_msg) + custom_msg++; + } + + /* scan kwlist and get greatest possible nbr of args */ + for (len=0; kwlist[len]; len++) + continue; + + 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)", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()", + len, + (len == 1) ? "" : "s", + nargs + nkeywords); + return 0; + } + + /* 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 == '|') { + min = i; + format++; + } + 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); + } + current_arg = NULL; + if (nkeywords) { + current_arg = PyDict_GetItemString(keywords, keyword); + } + if (current_arg) { + --nkeywords; + if (i < nargs) { + /* arg present in tuple and in dict */ + PyErr_Format(PyExc_TypeError, + "Argument given by name ('%s') " + "and position (%d)", + keyword, i+1); + return cleanreturn(0, freelist); + } + } + else if (nkeywords && PyErr_Occurred()) + return cleanreturn(0, freelist); + else if (i < nargs) + current_arg = PyTuple_GET_ITEM(args, i); + + if (current_arg) { + msg = convertitem(current_arg, &format, p_va, flags, + levels, msgbuf, sizeof(msgbuf), &freelist); + if (msg) { + seterror(i+1, msg, levels, fname, custom_msg); + return cleanreturn(0, freelist); + } + continue; + } + + if (i < min) { + PyErr_Format(PyExc_TypeError, "Required argument " + "'%s' (pos %d) not found", + keyword, i+1); + 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); + + /* We are into optional args, skip thru to any remaining + * keyword args */ + msg = skipitem(&format, p_va, flags); + if (msg) { + PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg, + format); + return cleanreturn(0, freelist); + } + } + + if (!IS_END_OF_FORMAT(*format) && *format != '|') { + PyErr_Format(PyExc_RuntimeError, + "more argument specifiers than keyword list entries " + "(remaining format:'%s')", format); + return cleanreturn(0, freelist); + } + + /* make sure there are no extraneous keyword arguments */ + if (nkeywords > 0) { + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(keywords, &pos, &key, &value)) { + int match = 0; + char *ks; + if (!PyUnicode_Check(key)) { + PyErr_SetString(PyExc_TypeError, + "keywords must be strings"); + return cleanreturn(0, freelist); + } + ks = _PyUnicode_AsString(key); + for (i = 0; i < len; i++) { + if (!strcmp(ks, kwlist[i])) { + match = 1; + break; + } + } + if (!match) { + PyErr_Format(PyExc_TypeError, + "'%s' is an invalid keyword " + "argument for this function", + ks); + return cleanreturn(0, freelist); + } + } + } + + return cleanreturn(1, freelist); } static char * skipitem(const char **p_format, va_list *p_va, int flags) { - const char *format = *p_format; - char c = *format++; - - switch (c) { - - /* simple codes - * The individual types (second arg of va_arg) are irrelevant */ - - case 'b': /* byte -- very short int */ - case 'B': /* byte as bitfield */ - case 'h': /* short int */ - case 'H': /* short int as bitfield */ - case 'i': /* int */ - case 'I': /* int sized bitfield */ - case 'l': /* long int */ - case 'k': /* long int sized bitfield */ + const char *format = *p_format; + char c = *format++; + + switch (c) { + + /* simple codes + * The individual types (second arg of va_arg) are irrelevant */ + + case 'b': /* byte -- very short int */ + case 'B': /* byte as bitfield */ + case 'h': /* short int */ + case 'H': /* short int as bitfield */ + case 'i': /* int */ + case 'I': /* int sized bitfield */ + case 'l': /* long int */ + case 'k': /* long int sized bitfield */ #ifdef HAVE_LONG_LONG - case 'L': /* PY_LONG_LONG */ - case 'K': /* PY_LONG_LONG sized bitfield */ + case 'L': /* PY_LONG_LONG */ + case 'K': /* PY_LONG_LONG sized bitfield */ #endif - case 'f': /* float */ - case 'd': /* double */ - case 'D': /* complex double */ - case 'c': /* char */ - case 'C': /* unicode char */ - { - (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 */ - { - (void) va_arg(*p_va, const char *); - if (!(*format == 's' || *format == 't')) - /* after 'e', only 's' and 't' is allowed */ - goto err; - format++; - /* explicit fallthrough to string cases */ - } - - case 's': /* string */ - case 'z': /* string or None */ - case 'y': /* bytes */ - case 'u': /* unicode string */ - case 't': /* buffer, read-only */ - case 'w': /* buffer, read-write */ - { - (void) va_arg(*p_va, char **); - if (*format == '#') { - if (flags & FLAG_SIZE_T) - (void) va_arg(*p_va, Py_ssize_t *); - else - (void) va_arg(*p_va, int *); - format++; - } else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') { - format++; - } - 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 == '!') { - format++; - (void) va_arg(*p_va, PyTypeObject*); - (void) va_arg(*p_va, PyObject **); - } - else if (*format == '&') { - typedef int (*converter)(PyObject *, void *); - (void) va_arg(*p_va, converter); - (void) va_arg(*p_va, void *); - format++; - } - else { - (void) va_arg(*p_va, PyObject **); - } - break; - } - - case '(': /* bypass tuple, not handled at all previously */ - { - char *msg; - for (;;) { - if (*format==')') - break; - if (IS_END_OF_FORMAT(*format)) - return "Unmatched left paren in format " - "string"; - msg = skipitem(&format, p_va, flags); - if (msg) - return msg; - } - format++; - break; - } - - case ')': - return "Unmatched right paren in format string"; - - default: + case 'f': /* float */ + case 'd': /* double */ + case 'D': /* complex double */ + case 'c': /* char */ + case 'C': /* unicode char */ + { + (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 */ + { + (void) va_arg(*p_va, const char *); + if (!(*format == 's' || *format == 't')) + /* after 'e', only 's' and 't' is allowed */ + goto err; + format++; + /* explicit fallthrough to string cases */ + } + + case 's': /* string */ + case 'z': /* string or None */ + case 'y': /* bytes */ + case 'u': /* unicode string */ + case 't': /* buffer, read-only */ + case 'w': /* buffer, read-write */ + { + (void) va_arg(*p_va, char **); + if (*format == '#') { + if (flags & FLAG_SIZE_T) + (void) va_arg(*p_va, Py_ssize_t *); + else + (void) va_arg(*p_va, int *); + format++; + } else if ((c == 's' || c == 'z' || c == 'y') && *format == '*') { + format++; + } + 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 == '!') { + format++; + (void) va_arg(*p_va, PyTypeObject*); + (void) va_arg(*p_va, PyObject **); + } + else if (*format == '&') { + typedef int (*converter)(PyObject *, void *); + (void) va_arg(*p_va, converter); + (void) va_arg(*p_va, void *); + format++; + } + else { + (void) va_arg(*p_va, PyObject **); + } + break; + } + + case '(': /* bypass tuple, not handled at all previously */ + { + char *msg; + for (;;) { + if (*format==')') + break; + if (IS_END_OF_FORMAT(*format)) + return "Unmatched left paren in format " + "string"; + msg = skipitem(&format, p_va, flags); + if (msg) + return msg; + } + format++; + break; + } + + case ')': + return "Unmatched right paren in format string"; + + default: err: - return "impossible"; + return "impossible"; - } + } - *p_format = format; - return NULL; + *p_format = format; + return NULL; } int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) { - Py_ssize_t i, l; - PyObject **o; - va_list vargs; + Py_ssize_t i, l; + PyObject **o; + va_list vargs; #ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, max); + va_start(vargs, max); #else - va_start(vargs); + va_start(vargs); #endif - assert(min >= 0); - assert(min <= max); - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_SystemError, - "PyArg_UnpackTuple() argument list is not a tuple"); - return 0; - } - l = PyTuple_GET_SIZE(args); - if (l < min) { - if (name != NULL) - PyErr_Format( - PyExc_TypeError, - "%s expected %s%zd arguments, got %zd", - name, (min == max ? "" : "at least "), min, l); - else - PyErr_Format( - PyExc_TypeError, - "unpacked tuple should have %s%zd elements," - " but has %zd", - (min == max ? "" : "at least "), min, l); - va_end(vargs); - return 0; - } - if (l > max) { - if (name != NULL) - PyErr_Format( - PyExc_TypeError, - "%s expected %s%zd arguments, got %zd", - name, (min == max ? "" : "at most "), max, l); - else - PyErr_Format( - PyExc_TypeError, - "unpacked tuple should have %s%zd elements," - " but has %zd", - (min == max ? "" : "at most "), max, l); - va_end(vargs); - return 0; - } - for (i = 0; i < l; i++) { - o = va_arg(vargs, PyObject **); - *o = PyTuple_GET_ITEM(args, i); - } - va_end(vargs); - return 1; + assert(min >= 0); + assert(min <= max); + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_SystemError, + "PyArg_UnpackTuple() argument list is not a tuple"); + return 0; + } + l = PyTuple_GET_SIZE(args); + if (l < min) { + if (name != NULL) + PyErr_Format( + PyExc_TypeError, + "%s expected %s%zd arguments, got %zd", + name, (min == max ? "" : "at least "), min, l); + else + PyErr_Format( + PyExc_TypeError, + "unpacked tuple should have %s%zd elements," + " but has %zd", + (min == max ? "" : "at least "), min, l); + va_end(vargs); + return 0; + } + if (l > max) { + if (name != NULL) + PyErr_Format( + PyExc_TypeError, + "%s expected %s%zd arguments, got %zd", + name, (min == max ? "" : "at most "), max, l); + else + PyErr_Format( + PyExc_TypeError, + "unpacked tuple should have %s%zd elements," + " but has %zd", + (min == max ? "" : "at most "), max, l); + va_end(vargs); + return 0; + } + for (i = 0; i < l; i++) { + o = va_arg(vargs, PyObject **); + *o = PyTuple_GET_ITEM(args, i); + } + va_end(vargs); + return 1; } @@ -1975,18 +1975,18 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m int _PyArg_NoKeywords(const char *funcname, PyObject *kw) { - if (kw == NULL) - return 1; - if (!PyDict_CheckExact(kw)) { - PyErr_BadInternalCall(); - return 0; - } - if (PyDict_Size(kw) == 0) - return 1; - - PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments", - funcname); - return 0; + if (kw == NULL) + return 1; + if (!PyDict_CheckExact(kw)) { + PyErr_BadInternalCall(); + return 0; + } + if (PyDict_Size(kw) == 0) + return 1; + + PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments", + funcname); + return 0; } #ifdef __cplusplus }; -- cgit v1.2.1 From 7cb80215eb0e3492f5227875ae546f981301703d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 19 May 2010 00:54:06 +0000 Subject: Issue #6697: Fix a crash if a keyword contains a surrogate --- Python/getargs.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 4fa2b5bffb..e8efb3c279 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1755,18 +1755,21 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, "keywords must be strings"); return cleanreturn(0, freelist); } + /* check that _PyUnicode_AsString() result is not NULL */ ks = _PyUnicode_AsString(key); - for (i = 0; i < len; i++) { - if (!strcmp(ks, kwlist[i])) { - match = 1; - break; + if (ks != NULL) { + for (i = 0; i < len; i++) { + if (!strcmp(ks, kwlist[i])) { + match = 1; + break; + } } } if (!match) { PyErr_Format(PyExc_TypeError, - "'%s' is an invalid keyword " + "'%U' is an invalid keyword " "argument for this function", - ks); + key); return cleanreturn(0, freelist); } } -- cgit v1.2.1 From dbf0531ca28d0bd7e848a01172204ba0e93479af Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 28 May 2010 21:55:10 +0000 Subject: Issue #8837: Remove "O?" format of PyArg_Parse*() functions. The format is no used anymore and it was never documented. --- Python/getargs.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index e8efb3c279..ce9f152c9f 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1292,17 +1292,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, else return converterr(type->tp_name, arg, msgbuf, bufsize); - } - else if (*format == '?') { - inquiry pred = va_arg(*p_va, inquiry); - p = va_arg(*p_va, PyObject **); - format++; - if ((*pred)(arg)) - *p = arg; - else - return converterr("(unspecified)", - arg, msgbuf, bufsize); - } else if (*format == '&') { typedef int (*converter)(PyObject *, void *); -- cgit v1.2.1 From a5149be3a59b4b56f6cbf22a65d637867bcb0cc5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 29 May 2010 00:13:06 +0000 Subject: Remove dead code --- Python/getargs.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index ce9f152c9f..4f7bf7a5d7 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1029,18 +1029,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, else return converterr("string or None", arg, msgbuf, bufsize); - if (*format == '#') { - FETCH_SIZE; - assert(0); /* XXX redundant with if-case */ - if (arg == Py_None) { - STORE_SIZE(0); - } - else { - STORE_SIZE(PyBytes_Size(arg)); - } - format++; - } - else if (*p != NULL && uarg != NULL && + if (*p != NULL && uarg != NULL && (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) return converterr( "string without null bytes or None", -- cgit v1.2.1 From dd156c4f9dd2cb07ac485895245f7c142fd2feb8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 6 Jun 2010 20:27:51 +0000 Subject: Simplify getbuffer(): convertbuffer() fails anyway if bf_getbuffer is NULL --- Python/getargs.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 4f7bf7a5d7..1806bf87ae 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1410,7 +1410,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, static Py_ssize_t convertbuffer(PyObject *arg, void **p, char **errmsg) { - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; Py_ssize_t count; Py_buffer view; @@ -1438,31 +1438,23 @@ convertbuffer(PyObject *arg, void **p, char **errmsg) static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - void *buf; - Py_ssize_t count; - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; if (pb == NULL) { *errmsg = "bytes or buffer"; return -1; } - if (pb->bf_getbuffer) { - if (PyObject_GetBuffer(arg, view, 0) < 0) { - *errmsg = "convertible to a buffer"; - return -1; - } - if (!PyBuffer_IsContiguous(view, 'C')) { - *errmsg = "contiguous buffer"; - return -1; - } - return 0; + if (pb->bf_getbuffer == NULL) { + *errmsg = "convertible to a buffer"; + return -1; } - - count = convertbuffer(arg, &buf, errmsg); - if (count < 0) { + if (PyObject_GetBuffer(arg, view, 0) < 0) { *errmsg = "convertible to a buffer"; - return count; + return -1; + } + if (!PyBuffer_IsContiguous(view, 'C')) { + *errmsg = "contiguous buffer"; + return -1; } - PyBuffer_FillInfo(view, NULL, buf, count, 1, 0); return 0; } -- cgit v1.2.1 From a12b7a5e8fa33d4f371cd34651714f027c5ea626 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 6 Jun 2010 20:38:02 +0000 Subject: convertsimple(): call PyErr_NoMemory() on PyMem_NEW() failure Raise a more revelant error (MemoryError instead of TypeError) --- Python/getargs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 1806bf87ae..b4b5db283c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1172,6 +1172,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); + PyErr_NoMemory(); return converterr( "(memory error)", arg, msgbuf, bufsize); @@ -1215,6 +1216,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); + PyErr_NoMemory(); return converterr("(memory error)", arg, msgbuf, bufsize); } -- cgit v1.2.1 From b6a0126b4eabe96869ef204f02261402bd02365b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 8 Jun 2010 21:45:51 +0000 Subject: PyArg_Parse*("Z#") raises an error for unknown type instead of ignoring the error and leave the pointer to the string and the size unchanged (not initialized). Fix also the type in the error message of "Z", "Z#" and "Y" formats. --- Python/getargs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index b4b5db283c..31b9d35716 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1051,6 +1051,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = PyUnicode_AS_UNICODE(arg); STORE_SIZE(PyUnicode_GET_SIZE(arg)); } + else + return converterr("str or None", arg, msgbuf, bufsize); format++; } else { Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); @@ -1060,8 +1062,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, else if (PyUnicode_Check(arg)) *p = PyUnicode_AS_UNICODE(arg); else - return converterr("string or None", - arg, msgbuf, bufsize); + return converterr("str or None", arg, msgbuf, bufsize); } break; } @@ -1258,7 +1259,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (PyByteArray_Check(arg)) *p = arg; else - return converterr("buffer", arg, msgbuf, bufsize); + return converterr("bytearray", arg, msgbuf, bufsize); break; } -- cgit v1.2.1 From 9d9d2dbc453236f7fa5555d17885e1eabbaf23f6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 8 Jun 2010 22:54:19 +0000 Subject: Issue #8838, #8339: Remove codecs.charbuffer_encode() and "t#" parsing format Remove last references to the "char buffer" of the buffer protocol from Python3. --- Python/getargs.c | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 31b9d35716..2a26a8f9f3 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -864,7 +864,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w', 't' codes all + /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all need to be cleaned up! */ case 's': {/* text string */ @@ -1362,45 +1362,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - /*TEO: This can be eliminated --- here only for backward - compatibility */ - case 't': { /* 8-bit character buffer, read-only access */ - char **p = va_arg(*p_va, char **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - Py_buffer view; - - if (*format++ != '#') - return converterr( - "invalid use of 't' format character", - arg, msgbuf, bufsize); - if (pb == NULL || pb->bf_getbuffer == NULL) - return converterr( - "bytes or read-only character buffer", - arg, msgbuf, bufsize); - - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) - return converterr("string or single-segment read-only buffer", - arg, msgbuf, bufsize); - - count = view.len; - *p = view.buf; - if (pb->bf_releasebuffer) - return converterr( - "string or pinned buffer", - arg, msgbuf, bufsize); - - PyBuffer_Release(&view); - - if (count < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - { - FETCH_SIZE; - STORE_SIZE(count); - } - break; - } - default: return converterr("impossible", arg, msgbuf, bufsize); -- cgit v1.2.1 From d00354254b00b4ae88c65010b3015b1f7c3fab65 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 10 Jun 2010 16:05:10 +0000 Subject: Issue #8950: Make PyArg_Parse* with 'L' code raise for float inputs, instead of warning. This makes it consistent with the other integer codes. --- Python/getargs.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 2a26a8f9f3..127b1473a6 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -582,19 +582,6 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) #define CONV_UNICODE "(unicode conversion error)" -/* explicitly check for float arguments when integers are expected. For now - * signal a warning. Returns true if an exception was raised. */ -static int -float_argument_warning(PyObject *arg) -{ - if (PyFloat_Check(arg) && - PyErr_Warn(PyExc_DeprecationWarning, - "integer argument expected, got float" )) - return 1; - else - return 0; -} - /* Explicitly check for float arguments when integers are expected. Return 1 for error, 0 if ok. */ static int @@ -791,14 +778,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'L': {/* PY_LONG_LONG */ PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); PY_LONG_LONG ival; - if (float_argument_warning(arg)) + if (float_argument_error(arg)) return converterr("long", arg, msgbuf, bufsize); ival = PyLong_AsLongLong(arg); - if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { + if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred()) return converterr("long", arg, msgbuf, bufsize); - } else { + else *p = ival; - } break; } -- cgit v1.2.1 From 9a25f2657511270dacd4bf55964921f620799839 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Jun 2010 18:21:50 +0000 Subject: Issue #8592: PyArg_Parse*() functions raise a TypeError for "y", "u" and "Z" formats if the string contains a null byte/character. Write unit tests for string formats. --- Python/getargs.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 127b1473a6..d4d8d8417b 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -935,10 +935,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, count = convertbuffer(arg, p, &buf); if (count < 0) return converterr(buf, arg, msgbuf, bufsize); - else if (*format == '#') { + if (*format == '#') { FETCH_SIZE; STORE_SIZE(count); format++; + } else { + if (strlen(*p) != count) + return converterr( + "bytes without null bytes", + arg, msgbuf, bufsize); } break; } @@ -1045,9 +1050,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (arg == Py_None) *p = 0; - else if (PyUnicode_Check(arg)) + else if (PyUnicode_Check(arg)) { *p = PyUnicode_AS_UNICODE(arg); - else + if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) + return converterr( + "str without null character or None", + arg, msgbuf, bufsize); + } else return converterr("str or None", arg, msgbuf, bufsize); } break; @@ -1227,6 +1236,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, FETCH_SIZE; STORE_SIZE(PyUnicode_GET_SIZE(arg)); format++; + } else { + if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) + return converterr( + "str without null character", + arg, msgbuf, bufsize); } break; } -- cgit v1.2.1 From 4364d850379c3b2d3838fb9727d0bc2711a5c1f8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Jun 2010 20:31:26 +0000 Subject: getargs.c: remove last reference to "t#" format "t#" format was removed from convertitem() (convertsimple) but not skipitem(). --- Python/getargs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index d4d8d8417b..20f4814e8b 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1768,7 +1768,6 @@ skipitem(const char **p_format, va_list *p_va, int flags) case 'z': /* string or None */ case 'y': /* bytes */ case 'u': /* unicode string */ - case 't': /* buffer, read-only */ case 'w': /* buffer, read-write */ { (void) va_arg(*p_va, char **); -- cgit v1.2.1 From d03298c85a782dc64e7204b110f9b5600dd4a3bd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Jun 2010 22:08:25 +0000 Subject: Issue #8949: "z" format of PyArg_Parse*() functions doesn't accept bytes objects, as described in the documentation. --- Python/getargs.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 20f4814e8b..bce99ae798 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1005,11 +1005,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (arg == Py_None) *p = 0; - else if (PyBytes_Check(arg)) { - /* Enable null byte check below */ - uarg = arg; - *p = PyBytes_AS_STRING(arg); - } else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); if (uarg == NULL) -- cgit v1.2.1 From ee0db16e8ebe529fdb25f6e8171d484ae7ba1715 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Jun 2010 22:31:12 +0000 Subject: PyArg_Parse*() functions: factorize code for s/z and u/Z formats --- Python/getargs.c | 121 ++++++++++++------------------------------------------- 1 file changed, 25 insertions(+), 96 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index bce99ae798..ab95e1e547 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -853,70 +853,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all need to be cleaned up! */ - case 's': {/* text string */ - if (*format == '*') { - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 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, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else if (*format == '#') { - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); - } - else { /* any buffer-like object */ - /* XXX Really? */ - char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - STORE_SIZE(count); - } - format++; - } else { - char **p = va_arg(*p_va, char **); - - if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - } - else - return converterr("string", arg, msgbuf, bufsize); - if ((Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) - return converterr("string without null bytes", - arg, msgbuf, bufsize); - } - break; - } - case 'y': {/* any buffer-like object, but not PyUnicode */ void **p = (void **)va_arg(*p_va, char **); char *buf; @@ -948,11 +884,14 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - case 'z': {/* like 's' or 's#', but None is okay, stored as NULL */ + case 's': /* text string */ + case 'z': /* text string or None */ + { if (*format == '*') { + /* "s*" or "z*" */ Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - if (arg == Py_None) + if (c == 'z' && arg == Py_None) PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); @@ -975,11 +914,12 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } format++; } else if (*format == '#') { /* any buffer-like object */ + /* "s#" or "z#" */ void **p = (void **)va_arg(*p_va, char **); FETCH_SIZE; - if (arg == Py_None) { - *p = 0; + if (c == 'z' && arg == Py_None) { + *p = NULL; STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { @@ -1000,11 +940,12 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } format++; } else { + /* "s" or "z" */ char **p = va_arg(*p_va, char **); uarg = NULL; - if (arg == Py_None) - *p = 0; + if (c == 'z' && arg == Py_None) + *p = NULL; else if (PyUnicode_Check(arg)) { uarg = UNICODE_DEFAULT_ENCODING(arg); if (uarg == NULL) @@ -1013,24 +954,28 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = PyBytes_AS_STRING(uarg); } else - return converterr("string or None", + 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)) return converterr( - "string without null bytes or None", + c == 'z' ? "str without null bytes or None" + : "str without null bytes", arg, msgbuf, bufsize); } break; } - case 'Z': {/* unicode, may be NULL (None) */ + case 'u': /* raw unicode buffer (Py_UNICODE *) */ + case 'Z': /* raw unicode buffer or None */ + { if (*format == '#') { /* any buffer-like object */ + /* "s#" or "Z#" */ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); FETCH_SIZE; - if (arg == Py_None) { - *p = 0; + if (c == 'Z' && arg == Py_None) { + *p = NULL; STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { @@ -1041,10 +986,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return converterr("str or None", arg, msgbuf, bufsize); format++; } else { + /* "s" or "Z" */ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (arg == Py_None) - *p = 0; + 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)) @@ -1052,7 +998,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, "str without null character or None", arg, msgbuf, bufsize); } else - return converterr("str or None", arg, msgbuf, bufsize); + return converterr(c == 'Z' ? "str or None" : "str", + arg, msgbuf, bufsize); } break; } @@ -1222,24 +1169,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - case 'u': {/* raw unicode buffer (Py_UNICODE *) */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (!PyUnicode_Check(arg)) - return converterr("str", arg, msgbuf, bufsize); - *p = PyUnicode_AS_UNICODE(arg); - if (*format == '#') { /* store pointer and size */ - FETCH_SIZE; - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - format++; - } else { - if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) - return converterr( - "str without null character", - arg, msgbuf, bufsize); - } - break; - } - case 'S': { /* PyBytes object */ PyObject **p = va_arg(*p_va, PyObject **); if (PyBytes_Check(arg)) -- cgit v1.2.1 From 547ff8c05e9b5e68709dcba8eeb86794753eb68b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Jun 2010 22:57:10 +0000 Subject: getbuffer(): release the buffer on error (if the buffer is not contiguous) --- Python/getargs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index ab95e1e547..41b4af56cf 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1340,6 +1340,7 @@ getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) return -1; } if (!PyBuffer_IsContiguous(view, 'C')) { + PyBuffer_Release(view); *errmsg = "contiguous buffer"; return -1; } -- cgit v1.2.1 From be9c850f53cefba77db579038f9093c9869a5d43 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 25 Jun 2010 00:02:38 +0000 Subject: Issue #8850: Remove "w" and "w#" formats from PyArg_Parse*() functions, use "w*" format instead. Add tests for "w*" format. --- Python/getargs.c | 64 +++++++++++++++----------------------------------------- 1 file changed, 17 insertions(+), 47 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 41b4af56cf..7b929481d2 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1231,58 +1231,28 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } - case 'w': { /* memory buffer, read-write access */ + case 'w': { /* "w*": memory buffer, read-write access */ void **p = va_arg(*p_va, void **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - int temp=-1; - Py_buffer view; - - if (pb && pb->bf_releasebuffer && *format != '*') - /* Buffer must be released, yet caller does not use - the Py_buffer protocol. */ - return converterr("pinned buffer", arg, msgbuf, bufsize); + if (*format != '*') + return converterr( + "invalid use of 'w' format character", + arg, msgbuf, bufsize); + format++; - if (pb && pb->bf_getbuffer && *format == '*') { - /* Caller is interested in Py_buffer, and the object - supports it directly. */ - format++; - if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); - return converterr("read-write buffer", arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) - return converterr("contiguous buffer", arg, msgbuf, bufsize); - break; - } - - /* Here we have processed w*, only w and w# remain. */ - if (pb == NULL || - pb->bf_getbuffer == NULL || - ((temp = PyObject_GetBuffer(arg, &view, - PyBUF_SIMPLE)) != 0) || - view.readonly == 1) { - if (temp==0) { - PyBuffer_Release(&view); - } - return converterr("single-segment read-write buffer", - arg, msgbuf, bufsize); + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write buffer", arg, msgbuf, bufsize); } - - if ((count = view.len) < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - *p = view.buf; - if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) + return converterr("contiguous buffer", arg, msgbuf, bufsize); break; } -- cgit v1.2.1 From ed5b199596c6d8fb8397e2f7ac93d24a59ebab5d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Jul 2010 00:40:58 +0000 Subject: Issue #8991: convertbuffer() rejects discontigious buffers --- Python/getargs.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 7b929481d2..e4bd50d7b3 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1246,13 +1246,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyErr_Clear(); return converterr("read-write buffer", arg, msgbuf, bufsize); } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { + PyBuffer_Release((Py_buffer*)p); + return converterr("contiguous buffer", arg, msgbuf, bufsize); + } if (addcleanup(p, freelist, cleanup_buffer)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) - return converterr("contiguous buffer", arg, msgbuf, bufsize); break; } @@ -1274,41 +1276,26 @@ convertbuffer(PyObject *arg, void **p, char **errmsg) *errmsg = NULL; *p = NULL; - if (pb == NULL || - pb->bf_getbuffer == NULL || - pb->bf_releasebuffer != NULL) { - *errmsg = "bytes or read-only buffer"; + if (pb != NULL && pb->bf_releasebuffer != NULL) { + *errmsg = "read-only pinned buffer"; return -1; } - if (PyObject_GetBuffer(arg, &view, PyBUF_SIMPLE) != 0) { - *errmsg = "bytes or single-segment read-only buffer"; + if (getbuffer(arg, &view, errmsg) < 0) return -1; - } count = view.len; *p = view.buf; PyBuffer_Release(&view); return count; } -/* XXX for 3.x, getbuffer and convertbuffer can probably - be merged again. */ static int getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; - if (pb == NULL) { + if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { *errmsg = "bytes or buffer"; return -1; } - if (pb->bf_getbuffer == NULL) { - *errmsg = "convertible to a buffer"; - return -1; - } - if (PyObject_GetBuffer(arg, view, 0) < 0) { - *errmsg = "convertible to a buffer"; - return -1; - } if (!PyBuffer_IsContiguous(view, 'C')) { PyBuffer_Release(view); *errmsg = "contiguous buffer"; -- cgit v1.2.1 From 35ce36d96009a24d4f588bf27c1c07e2af4fc822 Mon Sep 17 00:00:00 2001 From: Alexander Belopolsky Date: Wed, 11 Aug 2010 17:31:17 +0000 Subject: Issue #2443: Added a new macro, Py_VA_COPY, which is equivalent to C99 va_copy, but available on all python platforms. Untabified a few unrelated files. --- Python/getargs.c | 40 ++++------------------------------------ 1 file changed, 4 insertions(+), 36 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index e4bd50d7b3..abf55ce041 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -105,15 +105,7 @@ PyArg_VaParse(PyObject *args, const char *format, va_list va) { va_list lva; -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif + Py_VA_COPY(lva, va); return vgetargs1(args, format, &lva, 0); } @@ -123,15 +115,7 @@ _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) { va_list lva; -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif + Py_VA_COPY(lva, va); return vgetargs1(args, format, &lva, FLAG_SIZE_T); } @@ -1376,15 +1360,7 @@ PyArg_VaParseTupleAndKeywords(PyObject *args, return 0; } -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif + Py_VA_COPY(lva, va); retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); return retval; @@ -1408,15 +1384,7 @@ _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, return 0; } -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif + Py_VA_COPY(lva, va); retval = vgetargskeywords(args, keywords, format, kwlist, &lva, FLAG_SIZE_T); -- cgit v1.2.1 From c6988922ca2c06a951ebe4ea907421105ee96806 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 17 Nov 2010 22:33:12 +0000 Subject: handle dict subclasses gracefully in PyArg_ValidateKeywordArguments --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index abf55ce041..cf9869965c 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1394,7 +1394,7 @@ _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, int PyArg_ValidateKeywordArguments(PyObject *kwargs) { - if (!PyDict_CheckExact(kwargs)) { + if (!PyDict_Check(kwargs)) { PyErr_BadInternalCall(); return 0; } -- cgit v1.2.1 From a99a431f5ecdd9c7185eea5ab4bba79575ef92c6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Jan 2011 02:07:34 +0000 Subject: Issue #8651: PyArg_Parse*() functions raise an OverflowError if the file doesn't have PY_SSIZE_T_CLEAN define and the size doesn't fit in an int (length bigger than 2^31-1). --- Python/getargs.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index cf9869965c..aac1d177a7 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -597,7 +597,17 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, #define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\ if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \ else q=va_arg(*p_va, int*); -#define STORE_SIZE(s) if (flags & FLAG_SIZE_T) *q2=s; else *q=s; +#define STORE_SIZE(s) \ + if (flags & FLAG_SIZE_T) \ + *q2=s; \ + else { \ + if (INT_MAX < s) { \ + PyErr_SetString(PyExc_OverflowError, \ + "size does not fit in an int"); \ + return converterr("", arg, msgbuf, bufsize); \ + } \ + *q=s; \ + } #define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) const char *format = *p_format; -- cgit v1.2.1 From f4d435f0800e226d7b69b399f1d959e4909182fd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Jan 2011 11:16:48 +0000 Subject: Issue #8992: Simplify addcleanup() API Don't need to handle unknown destructor anymore. --- Python/getargs.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index aac1d177a7..487f1aa9c0 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -146,10 +146,19 @@ cleanup_buffer(PyObject *self) } static int -addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr) +addcleanup(void *ptr, PyObject **freelist, int is_buffer) { 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); @@ -159,13 +168,6 @@ addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr) } } - if (destr == cleanup_ptr) { - name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; - } else if (destr == cleanup_buffer) { - name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; - } else { - return -1; - } cobj = PyCapsule_New(ptr, name, destr); if (!cobj) { destr(ptr); @@ -855,7 +857,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, cleanup_buffer)) { + if (addcleanup(p, freelist, 1)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); @@ -901,7 +903,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } - if (addcleanup(p, freelist, cleanup_buffer)) { + if (addcleanup(p, freelist, 1)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); @@ -1109,7 +1111,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, "(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); return converterr( "(cleanup problem)", @@ -1152,7 +1154,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return converterr("(memory error)", arg, msgbuf, bufsize); } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { + if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize); @@ -1244,7 +1246,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, cleanup_buffer)) { + if (addcleanup(p, freelist, 1)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); -- cgit v1.2.1 From 6509b37bb8032193baa39e2526501b96bc763b75 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Jan 2011 11:16:49 +0000 Subject: Issue #8992: convertsimple() doesn't need to fill msgbuf if an error occurred Return msgbug on error is enough. --- Python/getargs.c | 79 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 487f1aa9c0..600941d9c7 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -611,6 +611,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *q=s; \ } #define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) +#define RETURN_ERR_OCCURRED return msgbuf const char *format = *p_format; char c = *format++; @@ -622,19 +623,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *p = va_arg(*p_va, char *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else if (ival < 0) { PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); + "unsigned byte integer is less than minimum"); + RETURN_ERR_OCCURRED; } else if (ival > UCHAR_MAX) { PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); + "unsigned byte integer is greater than maximum"); + RETURN_ERR_OCCURRED; } else *p = (unsigned char) ival; @@ -646,10 +647,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *p = va_arg(*p_va, char *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsUnsignedLongMask(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = (unsigned char) ival; break; @@ -659,19 +660,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, short *p = va_arg(*p_va, short *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else if (ival < SHRT_MIN) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed short integer is less than minimum"); + RETURN_ERR_OCCURRED; } else if (ival > SHRT_MAX) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed short integer is greater than maximum"); + RETURN_ERR_OCCURRED; } else *p = (short) ival; @@ -683,10 +684,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, unsigned short *p = va_arg(*p_va, unsigned short *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsUnsignedLongMask(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = (unsigned short) ival; break; @@ -696,19 +697,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *p = va_arg(*p_va, int *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else if (ival > INT_MAX) { PyErr_SetString(PyExc_OverflowError, - "signed integer is greater than maximum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed integer is greater than maximum"); + RETURN_ERR_OCCURRED; } else if (ival < INT_MIN) { PyErr_SetString(PyExc_OverflowError, - "signed integer is less than minimum"); - return converterr("integer", arg, msgbuf, bufsize); + "signed integer is less than minimum"); + RETURN_ERR_OCCURRED; } else *p = ival; @@ -720,10 +721,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, unsigned int *p = va_arg(*p_va, unsigned int *); unsigned int ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); if (ival == (unsigned int)-1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = ival; break; @@ -735,14 +736,14 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); Py_ssize_t ival = -1; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; iobj = PyNumber_Index(arg); if (iobj != NULL) { ival = PyLong_AsSsize_t(iobj); Py_DECREF(iobj); } if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; *p = ival; break; } @@ -750,10 +751,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, long *p = va_arg(*p_va, long *); long ival; if (float_argument_error(arg)) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - return converterr("integer", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = ival; break; @@ -775,10 +776,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); PY_LONG_LONG ival; if (float_argument_error(arg)) - return converterr("long", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; ival = PyLong_AsLongLong(arg); if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred()) - return converterr("long", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = ival; break; @@ -800,7 +801,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, float *p = va_arg(*p_va, float *); double dval = PyFloat_AsDouble(arg); if (PyErr_Occurred()) - return converterr("float", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = (float) dval; break; @@ -810,7 +811,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, double *p = va_arg(*p_va, double *); double dval = PyFloat_AsDouble(arg); if (PyErr_Occurred()) - return converterr("float", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = dval; break; @@ -821,7 +822,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, Py_complex cval; cval = PyComplex_AsCComplex(arg); if (PyErr_Occurred()) - return converterr("complex", arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; else *p = cval; break; @@ -1107,9 +1108,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (*buffer == NULL) { Py_DECREF(s); PyErr_NoMemory(); - return converterr( - "(memory error)", - arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; } if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); @@ -1151,8 +1150,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (*buffer == NULL) { Py_DECREF(s); PyErr_NoMemory(); - return converterr("(memory error)", - arg, msgbuf, bufsize); + RETURN_ERR_OCCURRED; } if (addcleanup(*buffer, freelist, 0)) { Py_DECREF(s); @@ -1261,6 +1259,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p_format = format; return NULL; + +#undef FETCH_SIZE +#undef STORE_SIZE +#undef BUFFER_LEN +#undef RETURN_ERR_OCCURRED } static Py_ssize_t -- cgit v1.2.1