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.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 1d36e1d..5433ff7 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -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;
 }