summaryrefslogtreecommitdiffstats
path: root/Python/getargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/getargs.c')
-rw-r--r--Python/getargs.c262
1 files changed, 202 insertions, 60 deletions
diff --git a/Python/getargs.c b/Python/getargs.c
index 9bcf9bc..0615577 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -15,21 +15,24 @@ int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
const char *, const char **, va_list);
+#define FLAG_COMPAT 1
+#define FLAG_SIZE_T 2
+
/* Forward */
static int vgetargs1(PyObject *, const char *, va_list *, int);
static void seterror(int, const char *, int *, const char *, const char *);
-static char *convertitem(PyObject *, const char **, va_list *, int *, char *,
- size_t, PyObject **);
-static char *converttuple(PyObject *, const char **, va_list *,
+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 **);
-static char *convertsimple(PyObject *, const char **, va_list *, char *,
+static char *convertsimple(PyObject *, const char **, va_list *, int, char *,
size_t, PyObject **);
-static int convertbuffer(PyObject *, void **p, char **);
+static Py_ssize_t convertbuffer(PyObject *, void **p, char **);
static int vgetargskeywords(PyObject *, PyObject *,
- const char *, const char **, va_list *);
-static char *skipitem(const char **, va_list *);
+ const char *, const char **, va_list *, int);
+static char *skipitem(const char **, va_list *, int);
int
PyArg_Parse(PyObject *args, const char *format, ...)
@@ -38,7 +41,19 @@ PyArg_Parse(PyObject *args, const char *format, ...)
va_list va;
va_start(va, format);
- retval = vgetargs1(args, format, &va, 1);
+ 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;
+
+ va_start(va, format);
+ retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T);
va_end(va);
return retval;
}
@@ -56,6 +71,18 @@ PyArg_ParseTuple(PyObject *args, const char *format, ...)
return retval;
}
+int
+_PyArg_ParseTuple_SizeT(PyObject *args, char *format, ...)
+{
+ int retval;
+ va_list va;
+
+ 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)
@@ -75,6 +102,24 @@ PyArg_VaParse(PyObject *args, const char *format, va_list va)
return vgetargs1(args, format, &lva, 0);
}
+int
+_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
+
+ return vgetargs1(args, format, &lva, FLAG_SIZE_T);
+}
+
/* Handle cleanup of allocated memory in case of exception */
@@ -120,7 +165,7 @@ cleanreturn(int retval, PyObject *freelist)
static int
-vgetargs1(PyObject *args, const char *format, va_list *p_va, int compat)
+vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
{
char msgbuf[256];
int levels[32];
@@ -134,8 +179,10 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int compat)
int 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++;
@@ -204,8 +251,8 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int compat)
PyErr_SetString(PyExc_TypeError, msgbuf);
return 0;
}
- msg = convertitem(args, &format, p_va, levels, msgbuf,
- sizeof(msgbuf), &freelist);
+ 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);
@@ -248,7 +295,8 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int compat)
if (*format == '|')
format++;
msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
- levels, msgbuf, sizeof(msgbuf), &freelist);
+ flags, levels, msgbuf,
+ sizeof(msgbuf), &freelist);
if (msg) {
seterror(i+1, msg, levels, fname, message);
return cleanreturn(0, freelist);
@@ -325,8 +373,9 @@ seterror(int iarg, const char *msg, int *levels, const char *fname,
*/
static char *
-converttuple(PyObject *arg, const char **p_format, va_list *p_va, int *levels,
- char *msgbuf, size_t bufsize, int toplevel, PyObject **freelist)
+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;
@@ -375,8 +424,8 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int *levels,
char *msg;
PyObject *item;
item = PySequence_GetItem(arg, i);
- msg = convertitem(item, &format, p_va, levels+1, msgbuf,
- bufsize, freelist);
+ 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) {
@@ -393,22 +442,22 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int *levels,
/* Convert a single item. */
static char *
-convertitem(PyObject *arg, const char **p_format, va_list *p_va, int *levels,
- char *msgbuf, size_t bufsize, PyObject **freelist)
+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, levels, msgbuf,
+ msg = converttuple(arg, &format, p_va, flags, levels, msgbuf,
bufsize, 0, freelist);
if (msg == NULL)
format++;
}
else {
- msg = convertsimple(arg, &format, p_va, msgbuf, bufsize,
- freelist);
+ msg = convertsimple(arg, &format, p_va, flags,
+ msgbuf, bufsize, freelist);
if (msg != NULL)
levels[0] = 0;
}
@@ -460,9 +509,16 @@ float_argument_error(PyObject *arg)
*/
static char *
-convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
+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*);
+#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++;
#ifdef Py_USING_UNICODE
@@ -544,7 +600,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
*p = (unsigned short) ival;
break;
}
-
+
case 'i': {/* signed int */
int *p = va_arg(*p_va, int *);
long ival;
@@ -582,6 +638,21 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
break;
}
+ case 'n': /* Py_ssize_t */
+#if SIZEOF_SIZE_T != SIZEOF_LONG
+ {
+ Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *);
+ Py_ssize_t ival;
+ if (float_argument_error(arg))
+ return converterr("integer<i>", arg, msgbuf, bufsize);
+ ival = PyInt_AsSsize_t(arg);
+ if (ival == -1 && PyErr_Occurred())
+ return converterr("integer<i>", arg, msgbuf, bufsize);
+ *p = ival;
+ break;
+ }
+#endif
+ /* Fall through from 'n' to 'l' if Py_ssize_t is int */
case 'l': {/* long int */
long *p = va_arg(*p_va, long *);
long ival;
@@ -679,11 +750,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
case 's': {/* string */
if (*format == '#') {
void **p = (void **)va_arg(*p_va, char **);
- int *q = va_arg(*p_va, int *);
+ FETCH_SIZE;
if (PyString_Check(arg)) {
*p = PyString_AS_STRING(arg);
- *q = PyString_GET_SIZE(arg);
+ STORE_SIZE(PyString_GET_SIZE(arg));
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(arg)) {
@@ -692,15 +763,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
return converterr(CONV_UNICODE,
arg, msgbuf, bufsize);
*p = PyString_AS_STRING(uarg);
- *q = PyString_GET_SIZE(uarg);
+ STORE_SIZE(PyString_GET_SIZE(uarg));
}
#endif
else { /* any buffer-like object */
char *buf;
- int count = convertbuffer(arg, p, &buf);
+ Py_ssize_t count = convertbuffer(arg, p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf, bufsize);
- *q = count;
+ STORE_SIZE(count);
}
format++;
} else {
@@ -729,15 +800,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
case 'z': {/* string, may be NULL (None) */
if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **);
- int *q = va_arg(*p_va, int *);
+ FETCH_SIZE;
if (arg == Py_None) {
*p = 0;
- *q = 0;
+ STORE_SIZE(0);
}
else if (PyString_Check(arg)) {
*p = PyString_AS_STRING(arg);
- *q = PyString_GET_SIZE(arg);
+ STORE_SIZE(PyString_GET_SIZE(arg));
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(arg)) {
@@ -746,15 +817,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
return converterr(CONV_UNICODE,
arg, msgbuf, bufsize);
*p = PyString_AS_STRING(uarg);
- *q = PyString_GET_SIZE(uarg);
+ STORE_SIZE(PyString_GET_SIZE(uarg));
}
#endif
else { /* any buffer-like object */
char *buf;
- int count = convertbuffer(arg, p, &buf);
+ Py_ssize_t count = convertbuffer(arg, p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf, bufsize);
- *q = count;
+ STORE_SIZE(count);
}
format++;
} else {
@@ -777,7 +848,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
return converterr("string or None",
arg, msgbuf, bufsize);
if (*format == '#') {
- int *q = va_arg(*p_va, int *);
+ FETCH_SIZE;
+ assert(0); // redundant with if-case
if (arg == Py_None)
*q = 0;
else
@@ -883,10 +955,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
trailing 0-byte
*/
- int *buffer_len = va_arg(*p_va, int *);
+ FETCH_SIZE;
format++;
- if (buffer_len == NULL) {
+ if (q == NULL && q2 == NULL) {
Py_DECREF(s);
return converterr(
"(buffer_len is NULL)",
@@ -907,7 +979,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
arg, msgbuf, bufsize);
}
} else {
- if (size + 1 > *buffer_len) {
+ if (size + 1 > BUFFER_LEN) {
Py_DECREF(s);
return converterr(
"(buffer overflow)",
@@ -917,7 +989,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
memcpy(*buffer,
PyString_AS_STRING(s),
size + 1);
- *buffer_len = size;
+ STORE_SIZE(size);
} else {
/* Using a 0-terminated buffer:
@@ -961,17 +1033,17 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
case 'u': {/* raw unicode buffer (Py_UNICODE *) */
if (*format == '#') { /* any buffer-like object */
void **p = (void **)va_arg(*p_va, char **);
- int *q = va_arg(*p_va, int *);
+ FETCH_SIZE;
if (PyUnicode_Check(arg)) {
*p = PyUnicode_AS_UNICODE(arg);
- *q = PyUnicode_GET_SIZE(arg);
+ STORE_SIZE(PyUnicode_GET_SIZE(arg));
}
else {
char *buf;
- int count = convertbuffer(arg, p, &buf);
+ Py_ssize_t count = convertbuffer(arg, p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf, bufsize);
- *q = count/(sizeof(Py_UNICODE));
+ STORE_SIZE(count/(sizeof(Py_UNICODE)));
}
format++;
} else {
@@ -1061,9 +1133,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
if ((count = pb->bf_getwritebuffer(arg, 0, p)) < 0)
return converterr("(unspecified)", arg, msgbuf, bufsize);
if (*format == '#') {
- int *q = va_arg(*p_va, int *);
-
- *q = count;
+ FETCH_SIZE;
+ STORE_SIZE(count);
format++;
}
break;
@@ -1094,7 +1165,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
count = pb->bf_getcharbuffer(arg, 0, p);
if (count < 0)
return converterr("(unspecified)", arg, msgbuf, bufsize);
- *va_arg(*p_va, int *) = count;
+ {
+ FETCH_SIZE;
+ STORE_SIZE(count);
+ }
break;
}
@@ -1107,11 +1181,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va,
return NULL;
}
-static int
+static Py_ssize_t
convertbuffer(PyObject *arg, void **p, char **errmsg)
{
PyBufferProcs *pb = arg->ob_type->tp_as_buffer;
- int count;
+ Py_ssize_t count;
if (pb == NULL ||
pb->bf_getreadbuffer == NULL ||
pb->bf_getsegcount == NULL) {
@@ -1151,7 +1225,32 @@ PyArg_ParseTupleAndKeywords(PyObject *args,
}
va_start(va, kwlist);
- retval = vgetargskeywords(args, keywords, format, kwlist, &va);
+ retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0);
+ va_end(va);
+ return retval;
+}
+
+int
+_PyArg_ParseTupleAndKeywords_SizeT(PyObject *args,
+ PyObject *keywords,
+ const char *format,
+ const 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;
}
@@ -1185,14 +1284,47 @@ PyArg_VaParseTupleAndKeywords(PyObject *args,
#endif
#endif
- retval = vgetargskeywords(args, keywords, format, kwlist, &lva);
+ retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0);
+ return retval;
+}
+
+int
+_PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args,
+ PyObject *keywords,
+ const char *format,
+ const 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;
+ }
+
+#ifdef VA_LIST_IS_ARRAY
+ memcpy(lva, va, sizeof(va_list));
+#else
+#ifdef __va_copy
+ __va_copy(lva, va);
+#else
+ lva = va;
+#endif
+#endif
+
+ retval = vgetargskeywords(args, keywords, format,
+ kwlist, &lva, FLAG_SIZE_T);
return retval;
}
static int
vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
- const char **kwlist, va_list *p_va)
+ const char **kwlist, va_list *p_va, int flags)
{
char msgbuf[512];
int levels[32];
@@ -1327,7 +1459,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
if (*format == '|')
format++;
msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
- levels, msgbuf, sizeof(msgbuf), &freelist);
+ flags, levels, msgbuf, sizeof(msgbuf),
+ &freelist);
if (msg) {
seterror(i+1, msg, levels, fname, message);
return cleanreturn(0, freelist);
@@ -1347,8 +1480,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
item = PyDict_GetItemString(keywords, kwlist[i]);
if (item != NULL) {
Py_INCREF(item);
- msg = convertitem(item, &format, p_va, levels, msgbuf,
- sizeof(msgbuf), &freelist);
+ msg = convertitem(item, &format, p_va, flags, levels,
+ msgbuf, sizeof(msgbuf), &freelist);
Py_DECREF(item);
if (msg) {
seterror(i+1, msg, levels, fname, message);
@@ -1361,7 +1494,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
else if (PyErr_Occurred())
return cleanreturn(0, freelist);
else {
- msg = skipitem(&format, p_va);
+ msg = skipitem(&format, p_va, flags);
if (msg) {
seterror(i+1, msg, levels, fname, message);
return cleanreturn(0, freelist);
@@ -1372,7 +1505,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
/* make sure there are no extraneous keyword arguments */
if (nkeywords > 0) {
PyObject *key, *value;
- int pos = 0;
+ Py_ssize_t pos = 0;
while (PyDict_Next(keywords, &pos, &key, &value)) {
int match = 0;
char *ks;
@@ -1403,7 +1536,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
static char *
-skipitem(const char **p_format, va_list *p_va)
+skipitem(const char **p_format, va_list *p_va, int flags)
{
const char *format = *p_format;
char c = *format++;
@@ -1435,6 +1568,12 @@ skipitem(const char **p_format, va_list *p_va)
(void) va_arg(*p_va, void *);
break;
}
+
+ case 'n': /* Py_ssize_t */
+ {
+ (void) va_arg(*p_va, Py_ssize_t *);
+ break;
+ }
/* string codes */
@@ -1458,7 +1597,10 @@ skipitem(const char **p_format, va_list *p_va)
{
(void) va_arg(*p_va, char **);
if (*format == '#') {
- (void) va_arg(*p_va, int *);
+ if (flags & FLAG_SIZE_T)
+ (void) va_arg(*p_va, Py_ssize_t *);
+ else
+ (void) va_arg(*p_va, int *);
format++;
}
break;