summaryrefslogtreecommitdiffstats
path: root/Objects/stringlib/string_format.h
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/stringlib/string_format.h')
-rw-r--r--Objects/stringlib/string_format.h51
1 files changed, 38 insertions, 13 deletions
diff --git a/Objects/stringlib/string_format.h b/Objects/stringlib/string_format.h
index b2095fd..c46bdc2 100644
--- a/Objects/stringlib/string_format.h
+++ b/Objects/stringlib/string_format.h
@@ -197,7 +197,6 @@ get_integer(const SubString *str)
{
Py_ssize_t accumulator = 0;
Py_ssize_t digitval;
- Py_ssize_t oldaccumulator;
STRINGLIB_CHAR *p;
/* empty string is an error */
@@ -209,19 +208,17 @@ get_integer(const SubString *str)
if (digitval < 0)
return -1;
/*
- This trick was copied from old Unicode format code. It's cute,
- but would really suck on an old machine with a slow divide
- implementation. Fortunately, in the normal case we do not
- expect too many digits.
+ Detect possible overflow before it happens:
+
+ accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if
+ accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
*/
- oldaccumulator = accumulator;
- accumulator *= 10;
- if ((accumulator+10)/10 != oldaccumulator+1) {
+ if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
PyErr_Format(PyExc_ValueError,
"Too many decimal digits in format string");
return -1;
}
- accumulator += digitval;
+ accumulator = accumulator * 10 + digitval;
}
return accumulator;
}
@@ -499,15 +496,28 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs,
PyObject *key = SubString_new_object(&first);
if (key == NULL)
goto error;
- if ((kwargs == NULL) || (obj = PyDict_GetItem(kwargs, key)) == NULL) {
+
+ /* Use PyObject_GetItem instead of PyDict_GetItem because this
+ code is no longer just used with kwargs. It might be passed
+ a non-dict when called through format_map. */
+ if ((kwargs == NULL) || (obj = PyObject_GetItem(kwargs, key)) == NULL) {
PyErr_SetObject(PyExc_KeyError, key);
Py_DECREF(key);
goto error;
}
Py_DECREF(key);
- Py_INCREF(obj);
}
else {
+ /* If args is NULL, we have a format string with a positional field
+ with only kwargs to retrieve it from. This can only happen when
+ used with format_map(), where positional arguments are not
+ allowed. */
+ if (args == NULL) {
+ PyErr_SetString(PyExc_ValueError, "Format string contains "
+ "positional fields");
+ goto error;
+ }
+
/* look up in args */
obj = PySequence_GetItem(args, index);
if (obj == NULL)
@@ -1039,6 +1049,11 @@ do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
return build_string(&input, args, kwargs, recursion_depth, &auto_number);
}
+static PyObject *
+do_string_format_map(PyObject *self, PyObject *obj)
+{
+ return do_string_format(self, NULL, obj);
+}
/************************************************************************/
@@ -1180,10 +1195,15 @@ static PyTypeObject PyFormatterIter_Type = {
describing the parsed elements. It's a wrapper around
stringlib/string_format.h's MarkupIterator */
static PyObject *
-formatter_parser(STRINGLIB_OBJECT *self)
+formatter_parser(PyObject *ignored, STRINGLIB_OBJECT *self)
{
formatteriterobject *it;
+ if (!PyUnicode_Check(self)) {
+ PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name);
+ return NULL;
+ }
+
it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
if (it == NULL)
return NULL;
@@ -1315,7 +1335,7 @@ static PyTypeObject PyFieldNameIter_Type = {
field_name_split. The iterator it returns is a
FieldNameIterator */
static PyObject *
-formatter_field_name_split(STRINGLIB_OBJECT *self)
+formatter_field_name_split(PyObject *ignored, STRINGLIB_OBJECT *self)
{
SubString first;
Py_ssize_t first_idx;
@@ -1324,6 +1344,11 @@ formatter_field_name_split(STRINGLIB_OBJECT *self)
PyObject *first_obj = NULL;
PyObject *result = NULL;
+ if (!PyUnicode_Check(self)) {
+ PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name);
+ return NULL;
+ }
+
it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
if (it == NULL)
return NULL;