[Python-checkins] r80450 - in python/branches/py3k: Doc/c-api/arg.rst Include/dictobject.h Include/modsupport.h Lib/test/test_dict.py Misc/NEWS Objects/dictobject.c Python/getargs.c
benjamin.peterson
python-checkins at python.org
Sat Apr 24 20:21:18 CEST 2010
Author: benjamin.peterson
Date: Sat Apr 24 20:21:17 2010
New Revision: 80450
Log:
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.
Modified:
python/branches/py3k/Doc/c-api/arg.rst
python/branches/py3k/Include/dictobject.h
python/branches/py3k/Include/modsupport.h
python/branches/py3k/Lib/test/test_dict.py
python/branches/py3k/Misc/NEWS
python/branches/py3k/Objects/dictobject.c
python/branches/py3k/Python/getargs.c
Modified: python/branches/py3k/Doc/c-api/arg.rst
==============================================================================
--- python/branches/py3k/Doc/c-api/arg.rst (original)
+++ python/branches/py3k/Doc/c-api/arg.rst Sat Apr 24 20:21:17 2010
@@ -366,6 +366,13 @@
va_list rather than a variable number of arguments.
+.. cfunction:: int PyArg_ValidateKeywordArguments(PyObject *)
+
+ Ensure that the keys in the keywords argument dictionary are strings. This
+ is only needed if :cfunc:`PyArg_ParseTupleAndKeywords` is not used, since the
+ latter already does this check.
+
+
.. XXX deprecated, will be removed
.. cfunction:: int PyArg_Parse(PyObject *args, const char *format, ...)
Modified: python/branches/py3k/Include/dictobject.h
==============================================================================
--- python/branches/py3k/Include/dictobject.h (original)
+++ python/branches/py3k/Include/dictobject.h Sat Apr 24 20:21:17 2010
@@ -126,6 +126,7 @@
PyAPI_FUNC(int) _PyDict_Contains(PyObject *mp, PyObject *key, long hash);
PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
PyAPI_FUNC(void) _PyDict_MaybeUntrack(PyObject *mp);
+PyAPI_FUNC(int) _PyDict_HasOnlyStringKeys(PyObject *mp);
/* PyDict_Update(mp, other) is equivalent to PyDict_Merge(mp, other, 1). */
PyAPI_FUNC(int) PyDict_Update(PyObject *mp, PyObject *other);
Modified: python/branches/py3k/Include/modsupport.h
==============================================================================
--- python/branches/py3k/Include/modsupport.h (original)
+++ python/branches/py3k/Include/modsupport.h Sat Apr 24 20:21:17 2010
@@ -27,6 +27,7 @@
PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *, const char *, ...) Py_FORMAT_PARSETUPLE(PyArg_ParseTuple, 2, 3);
PyAPI_FUNC(int) PyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
const char *, char **, ...);
+PyAPI_FUNC(int) PyArg_ValidateKeywordArguments(PyObject *);
PyAPI_FUNC(int) PyArg_UnpackTuple(PyObject *, const char *, Py_ssize_t, Py_ssize_t, ...);
PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...);
PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...);
Modified: python/branches/py3k/Lib/test/test_dict.py
==============================================================================
--- python/branches/py3k/Lib/test/test_dict.py (original)
+++ python/branches/py3k/Lib/test/test_dict.py Sat Apr 24 20:21:17 2010
@@ -7,6 +7,12 @@
class DictTest(unittest.TestCase):
+ def test_invalid_keyword_arguments(self):
+ with self.assertRaises(TypeError):
+ dict(**{1 : 2})
+ with self.assertRaises(TypeError):
+ {}.update(**{1 : 2})
+
def test_constructor(self):
# calling built-in types without argument must return empty
self.assertEqual(dict(), {})
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Sat Apr 24 20:21:17 2010
@@ -12,6 +12,9 @@
Core and Builtins
-----------------
+- Issue #8419: Prevent the dict constructor from accepting non-string keyword
+ arguments.
+
- Issue #8124: PySys_WriteStdout() and PySys_WriteStderr() don't execute
indirectly Python signal handlers anymore because mywrite() ignores
exceptions (KeyboardInterrupt)
@@ -282,6 +285,9 @@
C-API
-----
+- Add PyArg_ValidateKeywordArguments, which checks if all keyword arguments are
+ strings in an efficient manner.
+
- Issue #8276: PyEval_CallObject() is now only available in macro form. The
function declaration, which was kept for backwards compatibility reasons,
is now removed (the macro was introduced in 1997!).
Modified: python/branches/py3k/Objects/dictobject.c
==============================================================================
--- python/branches/py3k/Objects/dictobject.c (original)
+++ python/branches/py3k/Objects/dictobject.c Sat Apr 24 20:21:17 2010
@@ -458,6 +458,21 @@
return 0;
}
+int
+_PyDict_HasOnlyStringKeys(PyObject *dict)
+{
+ Py_ssize_t pos = 0;
+ PyObject *key, *value;
+ assert(PyDict_CheckExact(dict));
+ /* Shortcut */
+ if (((PyDictObject *)dict)->ma_lookup == lookdict_unicode)
+ return 1;
+ while (PyDict_Next(dict, &pos, &key, &value))
+ if (!PyUnicode_Check(key))
+ return 0;
+ return 1;
+}
+
#ifdef SHOW_TRACK_COUNT
#define INCREASE_TRACK_COUNT \
(count_tracked++, count_untracked--);
@@ -1386,8 +1401,12 @@
else
result = PyDict_MergeFromSeq2(self, arg, 1);
}
- if (result == 0 && kwds != NULL)
- result = PyDict_Merge(self, kwds, 1);
+ if (result == 0 && kwds != NULL) {
+ if (PyArg_ValidateKeywordArguments(kwds))
+ result = PyDict_Merge(self, kwds, 1);
+ else
+ result = -1;
+ }
return result;
}
Modified: python/branches/py3k/Python/getargs.c
==============================================================================
--- python/branches/py3k/Python/getargs.c (original)
+++ python/branches/py3k/Python/getargs.c Sat Apr 24 20:21:17 2010
@@ -1607,6 +1607,21 @@
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
More information about the Python-checkins
mailing list