gh-117557: Improve error messages when a string, bytes or bytearray of length 1 are expected (GH-117631)

This commit is contained in:
Serhiy Storchaka 2024-05-28 12:01:37 +03:00 committed by GitHub
parent bf08f0a5fe
commit b313cc68d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 811 additions and 161 deletions

View File

@ -550,10 +550,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 1) { if (nargs < 1) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[0]) && PyBytes_GET_SIZE(args[0]) == 1) { if (PyBytes_Check(args[0])) {
if (PyBytes_GET_SIZE(args[0]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 1 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[0]));
goto exit;
}
a = PyBytes_AS_STRING(args[0])[0]; a = PyBytes_AS_STRING(args[0])[0];
} }
else if (PyByteArray_Check(args[0]) && PyByteArray_GET_SIZE(args[0]) == 1) { else if (PyByteArray_Check(args[0])) {
if (PyByteArray_GET_SIZE(args[0]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 1 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[0]));
goto exit;
}
a = PyByteArray_AS_STRING(args[0])[0]; a = PyByteArray_AS_STRING(args[0])[0];
} }
else { else {
@ -563,10 +577,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 2) { if (nargs < 2) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[1]) && PyBytes_GET_SIZE(args[1]) == 1) { if (PyBytes_Check(args[1])) {
if (PyBytes_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 2 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[1]));
goto exit;
}
b = PyBytes_AS_STRING(args[1])[0]; b = PyBytes_AS_STRING(args[1])[0];
} }
else if (PyByteArray_Check(args[1]) && PyByteArray_GET_SIZE(args[1]) == 1) { else if (PyByteArray_Check(args[1])) {
if (PyByteArray_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 2 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[1]));
goto exit;
}
b = PyByteArray_AS_STRING(args[1])[0]; b = PyByteArray_AS_STRING(args[1])[0];
} }
else { else {
@ -576,10 +604,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 3) { if (nargs < 3) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[2]) && PyBytes_GET_SIZE(args[2]) == 1) { if (PyBytes_Check(args[2])) {
if (PyBytes_GET_SIZE(args[2]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 3 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[2]));
goto exit;
}
c = PyBytes_AS_STRING(args[2])[0]; c = PyBytes_AS_STRING(args[2])[0];
} }
else if (PyByteArray_Check(args[2]) && PyByteArray_GET_SIZE(args[2]) == 1) { else if (PyByteArray_Check(args[2])) {
if (PyByteArray_GET_SIZE(args[2]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 3 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[2]));
goto exit;
}
c = PyByteArray_AS_STRING(args[2])[0]; c = PyByteArray_AS_STRING(args[2])[0];
} }
else { else {
@ -589,10 +631,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 4) { if (nargs < 4) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[3]) && PyBytes_GET_SIZE(args[3]) == 1) { if (PyBytes_Check(args[3])) {
if (PyBytes_GET_SIZE(args[3]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 4 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[3]));
goto exit;
}
d = PyBytes_AS_STRING(args[3])[0]; d = PyBytes_AS_STRING(args[3])[0];
} }
else if (PyByteArray_Check(args[3]) && PyByteArray_GET_SIZE(args[3]) == 1) { else if (PyByteArray_Check(args[3])) {
if (PyByteArray_GET_SIZE(args[3]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 4 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[3]));
goto exit;
}
d = PyByteArray_AS_STRING(args[3])[0]; d = PyByteArray_AS_STRING(args[3])[0];
} }
else { else {
@ -602,10 +658,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 5) { if (nargs < 5) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[4]) && PyBytes_GET_SIZE(args[4]) == 1) { if (PyBytes_Check(args[4])) {
if (PyBytes_GET_SIZE(args[4]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 5 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[4]));
goto exit;
}
e = PyBytes_AS_STRING(args[4])[0]; e = PyBytes_AS_STRING(args[4])[0];
} }
else if (PyByteArray_Check(args[4]) && PyByteArray_GET_SIZE(args[4]) == 1) { else if (PyByteArray_Check(args[4])) {
if (PyByteArray_GET_SIZE(args[4]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 5 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[4]));
goto exit;
}
e = PyByteArray_AS_STRING(args[4])[0]; e = PyByteArray_AS_STRING(args[4])[0];
} }
else { else {
@ -615,10 +685,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 6) { if (nargs < 6) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[5]) && PyBytes_GET_SIZE(args[5]) == 1) { if (PyBytes_Check(args[5])) {
if (PyBytes_GET_SIZE(args[5]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 6 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[5]));
goto exit;
}
f = PyBytes_AS_STRING(args[5])[0]; f = PyBytes_AS_STRING(args[5])[0];
} }
else if (PyByteArray_Check(args[5]) && PyByteArray_GET_SIZE(args[5]) == 1) { else if (PyByteArray_Check(args[5])) {
if (PyByteArray_GET_SIZE(args[5]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 6 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[5]));
goto exit;
}
f = PyByteArray_AS_STRING(args[5])[0]; f = PyByteArray_AS_STRING(args[5])[0];
} }
else { else {
@ -628,10 +712,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 7) { if (nargs < 7) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[6]) && PyBytes_GET_SIZE(args[6]) == 1) { if (PyBytes_Check(args[6])) {
if (PyBytes_GET_SIZE(args[6]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 7 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[6]));
goto exit;
}
g = PyBytes_AS_STRING(args[6])[0]; g = PyBytes_AS_STRING(args[6])[0];
} }
else if (PyByteArray_Check(args[6]) && PyByteArray_GET_SIZE(args[6]) == 1) { else if (PyByteArray_Check(args[6])) {
if (PyByteArray_GET_SIZE(args[6]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 7 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[6]));
goto exit;
}
g = PyByteArray_AS_STRING(args[6])[0]; g = PyByteArray_AS_STRING(args[6])[0];
} }
else { else {
@ -641,10 +739,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 8) { if (nargs < 8) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[7]) && PyBytes_GET_SIZE(args[7]) == 1) { if (PyBytes_Check(args[7])) {
if (PyBytes_GET_SIZE(args[7]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 8 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[7]));
goto exit;
}
h = PyBytes_AS_STRING(args[7])[0]; h = PyBytes_AS_STRING(args[7])[0];
} }
else if (PyByteArray_Check(args[7]) && PyByteArray_GET_SIZE(args[7]) == 1) { else if (PyByteArray_Check(args[7])) {
if (PyByteArray_GET_SIZE(args[7]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 8 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[7]));
goto exit;
}
h = PyByteArray_AS_STRING(args[7])[0]; h = PyByteArray_AS_STRING(args[7])[0];
} }
else { else {
@ -654,10 +766,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 9) { if (nargs < 9) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[8]) && PyBytes_GET_SIZE(args[8]) == 1) { if (PyBytes_Check(args[8])) {
if (PyBytes_GET_SIZE(args[8]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 9 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[8]));
goto exit;
}
i = PyBytes_AS_STRING(args[8])[0]; i = PyBytes_AS_STRING(args[8])[0];
} }
else if (PyByteArray_Check(args[8]) && PyByteArray_GET_SIZE(args[8]) == 1) { else if (PyByteArray_Check(args[8])) {
if (PyByteArray_GET_SIZE(args[8]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 9 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[8]));
goto exit;
}
i = PyByteArray_AS_STRING(args[8])[0]; i = PyByteArray_AS_STRING(args[8])[0];
} }
else { else {
@ -667,10 +793,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 10) { if (nargs < 10) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[9]) && PyBytes_GET_SIZE(args[9]) == 1) { if (PyBytes_Check(args[9])) {
if (PyBytes_GET_SIZE(args[9]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 10 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[9]));
goto exit;
}
j = PyBytes_AS_STRING(args[9])[0]; j = PyBytes_AS_STRING(args[9])[0];
} }
else if (PyByteArray_Check(args[9]) && PyByteArray_GET_SIZE(args[9]) == 1) { else if (PyByteArray_Check(args[9])) {
if (PyByteArray_GET_SIZE(args[9]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 10 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[9]));
goto exit;
}
j = PyByteArray_AS_STRING(args[9])[0]; j = PyByteArray_AS_STRING(args[9])[0];
} }
else { else {
@ -680,10 +820,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 11) { if (nargs < 11) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[10]) && PyBytes_GET_SIZE(args[10]) == 1) { if (PyBytes_Check(args[10])) {
if (PyBytes_GET_SIZE(args[10]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 11 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[10]));
goto exit;
}
k = PyBytes_AS_STRING(args[10])[0]; k = PyBytes_AS_STRING(args[10])[0];
} }
else if (PyByteArray_Check(args[10]) && PyByteArray_GET_SIZE(args[10]) == 1) { else if (PyByteArray_Check(args[10])) {
if (PyByteArray_GET_SIZE(args[10]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 11 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[10]));
goto exit;
}
k = PyByteArray_AS_STRING(args[10])[0]; k = PyByteArray_AS_STRING(args[10])[0];
} }
else { else {
@ -693,10 +847,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 12) { if (nargs < 12) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[11]) && PyBytes_GET_SIZE(args[11]) == 1) { if (PyBytes_Check(args[11])) {
if (PyBytes_GET_SIZE(args[11]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 12 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[11]));
goto exit;
}
l = PyBytes_AS_STRING(args[11])[0]; l = PyBytes_AS_STRING(args[11])[0];
} }
else if (PyByteArray_Check(args[11]) && PyByteArray_GET_SIZE(args[11]) == 1) { else if (PyByteArray_Check(args[11])) {
if (PyByteArray_GET_SIZE(args[11]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 12 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[11]));
goto exit;
}
l = PyByteArray_AS_STRING(args[11])[0]; l = PyByteArray_AS_STRING(args[11])[0];
} }
else { else {
@ -706,10 +874,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 13) { if (nargs < 13) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[12]) && PyBytes_GET_SIZE(args[12]) == 1) { if (PyBytes_Check(args[12])) {
if (PyBytes_GET_SIZE(args[12]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 13 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[12]));
goto exit;
}
m = PyBytes_AS_STRING(args[12])[0]; m = PyBytes_AS_STRING(args[12])[0];
} }
else if (PyByteArray_Check(args[12]) && PyByteArray_GET_SIZE(args[12]) == 1) { else if (PyByteArray_Check(args[12])) {
if (PyByteArray_GET_SIZE(args[12]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 13 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[12]));
goto exit;
}
m = PyByteArray_AS_STRING(args[12])[0]; m = PyByteArray_AS_STRING(args[12])[0];
} }
else { else {
@ -719,10 +901,24 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 14) { if (nargs < 14) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[13]) && PyBytes_GET_SIZE(args[13]) == 1) { if (PyBytes_Check(args[13])) {
if (PyBytes_GET_SIZE(args[13]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 14 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[13]));
goto exit;
}
n = PyBytes_AS_STRING(args[13])[0]; n = PyBytes_AS_STRING(args[13])[0];
} }
else if (PyByteArray_Check(args[13]) && PyByteArray_GET_SIZE(args[13]) == 1) { else if (PyByteArray_Check(args[13])) {
if (PyByteArray_GET_SIZE(args[13]) != 1) {
PyErr_Format(PyExc_TypeError,
"test_char_converter(): argument 14 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[13]));
goto exit;
}
n = PyByteArray_AS_STRING(args[13])[0]; n = PyByteArray_AS_STRING(args[13])[0];
} }
else { else {
@ -740,7 +936,7 @@ static PyObject *
test_char_converter_impl(PyObject *module, char a, char b, char c, char d, test_char_converter_impl(PyObject *module, char a, char b, char c, char d,
char e, char f, char g, char h, char i, char j, char e, char f, char g, char h, char i, char j,
char k, char l, char m, char n) char k, char l, char m, char n)
/*[clinic end generated code: output=98589f02422fe6b1 input=e42330417a44feac]*/ /*[clinic end generated code: output=ff11e203248582df input=e42330417a44feac]*/
/*[clinic input] /*[clinic input]
@ -1028,7 +1224,10 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(args[2]) != 1) { if (PyUnicode_GET_LENGTH(args[2]) != 1) {
_PyArg_BadArgument("test_int_converter", "argument 3", "a unicode character", args[2]); PyErr_Format(PyExc_TypeError,
"test_int_converter(): argument 3 must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(args[2]));
goto exit; goto exit;
} }
c = PyUnicode_READ_CHAR(args[2], 0); c = PyUnicode_READ_CHAR(args[2], 0);
@ -1048,7 +1247,7 @@ exit:
static PyObject * static PyObject *
test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d) test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d)
/*[clinic end generated code: output=5aed87a7589eefb2 input=d20541fc1ca0553e]*/ /*[clinic end generated code: output=fbcfb7554688663d input=d20541fc1ca0553e]*/
/*[clinic input] /*[clinic input]

View File

@ -2,7 +2,7 @@ import ctypes
import sys import sys
import unittest import unittest
from ctypes import (CDLL, Structure, Array, CFUNCTYPE, from ctypes import (CDLL, Structure, Array, CFUNCTYPE,
byref, POINTER, pointer, ArgumentError, byref, POINTER, pointer, ArgumentError, sizeof,
c_char, c_wchar, c_byte, c_char_p, c_wchar_p, c_char, c_wchar, c_byte, c_char_p, c_wchar_p,
c_short, c_int, c_long, c_longlong, c_void_p, c_short, c_int, c_long, c_longlong, c_void_p,
c_float, c_double, c_longdouble) c_float, c_double, c_longdouble)
@ -72,7 +72,8 @@ class FunctionTestCase(unittest.TestCase):
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"argument 1: TypeError: one character bytes, " "argument 1: TypeError: one character bytes, "
"bytearray or integer expected") "bytearray, or an integer in range(256) expected, "
"not bytes of length 3")
def test_wchar_parm(self): def test_wchar_parm(self):
f = dll._testfunc_i_bhilfd f = dll._testfunc_i_bhilfd
@ -84,14 +85,27 @@ class FunctionTestCase(unittest.TestCase):
with self.assertRaises(ArgumentError) as cm: with self.assertRaises(ArgumentError) as cm:
f(1, 2, 3, 4, 5.0, 6.0) f(1, 2, 3, 4, 5.0, 6.0)
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"argument 2: TypeError: unicode string expected " "argument 2: TypeError: a unicode character expected, "
"instead of int instance") "not instance of int")
with self.assertRaises(ArgumentError) as cm: with self.assertRaises(ArgumentError) as cm:
f(1, "abc", 3, 4, 5.0, 6.0) f(1, "abc", 3, 4, 5.0, 6.0)
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"argument 2: TypeError: one character unicode string " "argument 2: TypeError: a unicode character expected, "
"expected") "not a string of length 3")
with self.assertRaises(ArgumentError) as cm:
f(1, "", 3, 4, 5.0, 6.0)
self.assertEqual(str(cm.exception),
"argument 2: TypeError: a unicode character expected, "
"not a string of length 0")
if sizeof(c_wchar) < 4:
with self.assertRaises(ArgumentError) as cm:
f(1, "\U0001f40d", 3, 4, 5.0, 6.0)
self.assertEqual(str(cm.exception),
"argument 2: TypeError: the string '\\U0001f40d' "
"cannot be converted to a single wchar_t character")
def test_c_char_p_parm(self): def test_c_char_p_parm(self):
"""Test the error message when converting an incompatible type to c_char_p.""" """Test the error message when converting an incompatible type to c_char_p."""

View File

@ -3,7 +3,7 @@ import test.support
from ctypes import (CDLL, PyDLL, ArgumentError, from ctypes import (CDLL, PyDLL, ArgumentError,
Structure, Array, Union, Structure, Array, Union,
_Pointer, _SimpleCData, _CFuncPtr, _Pointer, _SimpleCData, _CFuncPtr,
POINTER, pointer, byref, POINTER, pointer, byref, sizeof,
c_void_p, c_char_p, c_wchar_p, py_object, c_void_p, c_char_p, c_wchar_p, py_object,
c_bool, c_bool,
c_char, c_wchar, c_char, c_wchar,
@ -87,19 +87,33 @@ class SimpleTypesTestCase(unittest.TestCase):
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
c_char.from_param(b"abc") c_char.from_param(b"abc")
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"one character bytes, bytearray or integer expected") "one character bytes, bytearray, or an integer "
"in range(256) expected, not bytes of length 3")
def test_c_wchar(self): def test_c_wchar(self):
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
c_wchar.from_param("abc") c_wchar.from_param("abc")
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"one character unicode string expected") "a unicode character expected, not a string of length 3")
with self.assertRaises(TypeError) as cm:
c_wchar.from_param("")
self.assertEqual(str(cm.exception),
"a unicode character expected, not a string of length 0")
with self.assertRaises(TypeError) as cm: with self.assertRaises(TypeError) as cm:
c_wchar.from_param(123) c_wchar.from_param(123)
self.assertEqual(str(cm.exception), self.assertEqual(str(cm.exception),
"unicode string expected instead of int instance") "a unicode character expected, not instance of int")
if sizeof(c_wchar) < 4:
with self.assertRaises(TypeError) as cm:
c_wchar.from_param('\U0001f40d')
self.assertEqual(str(cm.exception),
"the string '\\U0001f40d' cannot be converted to "
"a single wchar_t character")
def test_int_pointers(self): def test_int_pointers(self):
LPINT = POINTER(c_int) LPINT = POINTER(c_int)

View File

@ -1578,7 +1578,7 @@ class StrTest(string_tests.StringLikeTest,
self.assertRaisesRegex(TypeError, '%u format: a real number is required, not complex', operator.mod, '%u', 3j) self.assertRaisesRegex(TypeError, '%u format: a real number is required, not complex', operator.mod, '%u', 3j)
self.assertRaisesRegex(TypeError, '%i format: a real number is required, not complex', operator.mod, '%i', 2j) self.assertRaisesRegex(TypeError, '%i format: a real number is required, not complex', operator.mod, '%i', 2j)
self.assertRaisesRegex(TypeError, '%d format: a real number is required, not complex', operator.mod, '%d', 1j) self.assertRaisesRegex(TypeError, '%d format: a real number is required, not complex', operator.mod, '%d', 1j)
self.assertRaisesRegex(TypeError, '%c requires int or char', operator.mod, '%c', pi) self.assertRaisesRegex(TypeError, r'%c requires an int or a unicode character, not .*\.PseudoFloat', operator.mod, '%c', pi)
class RaisingNumber: class RaisingNumber:
def __int__(self): def __int__(self):

View File

@ -0,0 +1,2 @@
Improve error messages when a string, bytes or bytearray object of length 1
is expected.

View File

@ -1100,25 +1100,45 @@ O_set(void *ptr, PyObject *value, Py_ssize_t size)
static PyObject * static PyObject *
c_set(void *ptr, PyObject *value, Py_ssize_t size) c_set(void *ptr, PyObject *value, Py_ssize_t size)
{ {
if (PyBytes_Check(value) && PyBytes_GET_SIZE(value) == 1) { if (PyBytes_Check(value)) {
if (PyBytes_GET_SIZE(value) != 1) {
PyErr_Format(PyExc_TypeError,
"one character bytes, bytearray, or an integer "
"in range(256) expected, not bytes of length %zd",
PyBytes_GET_SIZE(value));
return NULL;
}
*(char *)ptr = PyBytes_AS_STRING(value)[0]; *(char *)ptr = PyBytes_AS_STRING(value)[0];
_RET(value); _RET(value);
} }
if (PyByteArray_Check(value) && PyByteArray_GET_SIZE(value) == 1) { if (PyByteArray_Check(value)) {
if (PyByteArray_GET_SIZE(value) != 1) {
PyErr_Format(PyExc_TypeError,
"one character bytes, bytearray, or an integer "
"in range(256) expected, not bytearray of length %zd",
PyByteArray_GET_SIZE(value));
return NULL;
}
*(char *)ptr = PyByteArray_AS_STRING(value)[0]; *(char *)ptr = PyByteArray_AS_STRING(value)[0];
_RET(value); _RET(value);
} }
if (PyLong_Check(value)) if (PyLong_Check(value)) {
{ int overflow;
long longval = PyLong_AsLong(value); long longval = PyLong_AsLongAndOverflow(value, &overflow);
if (longval < 0 || longval >= 256) if (longval == -1 && PyErr_Occurred()) {
goto error; return NULL;
}
if (overflow || longval < 0 || longval >= 256) {
PyErr_SetString(PyExc_TypeError, "integer not in range(256)");
return NULL;
}
*(char *)ptr = (char)longval; *(char *)ptr = (char)longval;
_RET(value); _RET(value);
} }
error:
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"one character bytes, bytearray or integer expected"); "one character bytes, bytearray, or an integer "
"in range(256) expected, not %T",
value);
return NULL; return NULL;
} }
@ -1137,22 +1157,27 @@ u_set(void *ptr, PyObject *value, Py_ssize_t size)
wchar_t chars[2]; wchar_t chars[2];
if (!PyUnicode_Check(value)) { if (!PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"unicode string expected instead of %s instance", "a unicode character expected, not instance of %T",
Py_TYPE(value)->tp_name); value);
return NULL; return NULL;
} else }
Py_INCREF(value);
len = PyUnicode_AsWideChar(value, chars, 2); len = PyUnicode_AsWideChar(value, chars, 2);
if (len != 1) { if (len != 1) {
Py_DECREF(value); if (PyUnicode_GET_LENGTH(value) != 1) {
PyErr_SetString(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"one character unicode string expected"); "a unicode character expected, not a string of length %zd",
PyUnicode_GET_LENGTH(value));
}
else {
PyErr_Format(PyExc_TypeError,
"the string %A cannot be converted to a single wchar_t character",
value);
}
return NULL; return NULL;
} }
*(wchar_t *)ptr = chars[0]; *(wchar_t *)ptr = chars[0];
Py_DECREF(value);
_RET(value); _RET(value);
} }

View File

@ -233,13 +233,20 @@ static int
PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch) PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch)
{ {
long value; long value;
if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { if (PyBytes_Check(obj)) {
if (PyBytes_GET_SIZE(obj) != 1) {
PyErr_Format(PyExc_TypeError,
"expect int or bytes or str of length 1, "
"got a bytes of length %zd",
PyBytes_GET_SIZE(obj));
return 0;
}
value = (unsigned char)PyBytes_AsString(obj)[0]; value = (unsigned char)PyBytes_AsString(obj)[0];
} }
else if (PyUnicode_Check(obj)) { else if (PyUnicode_Check(obj)) {
if (PyUnicode_GetLength(obj) != 1) { if (PyUnicode_GET_LENGTH(obj) != 1) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expect bytes or str of length 1, or int, " "expect int or bytes or str of length 1, "
"got a str of length %zi", "got a str of length %zi",
PyUnicode_GET_LENGTH(obj)); PyUnicode_GET_LENGTH(obj));
return 0; return 0;
@ -272,7 +279,7 @@ PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch)
} }
else { else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expect bytes or str of length 1, or int, got %s", "expect int or bytes or str of length 1, got %s",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return 0; return 0;
} }
@ -315,7 +322,7 @@ PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj,
#ifdef HAVE_NCURSESW #ifdef HAVE_NCURSESW
if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) { if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expect bytes or str of length 1, or int, " "expect int or bytes or str of length 1, "
"got a str of length %zi", "got a str of length %zi",
PyUnicode_GET_LENGTH(obj)); PyUnicode_GET_LENGTH(obj));
return 0; return 0;
@ -326,7 +333,14 @@ PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj,
return PyCurses_ConvertToChtype(win, obj, ch); return PyCurses_ConvertToChtype(win, obj, ch);
#endif #endif
} }
else if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { else if (PyBytes_Check(obj)) {
if (PyBytes_GET_SIZE(obj) != 1) {
PyErr_Format(PyExc_TypeError,
"expect int or bytes or str of length 1, "
"got a bytes of length %zd",
PyBytes_GET_SIZE(obj));
return 0;
}
value = (unsigned char)PyBytes_AsString(obj)[0]; value = (unsigned char)PyBytes_AsString(obj)[0];
} }
else if (PyLong_CheckExact(obj)) { else if (PyLong_CheckExact(obj)) {
@ -340,7 +354,7 @@ PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj,
} }
else { else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expect bytes or str of length 1, or int, got %s", "expect int or bytes or str of length 1, got %s",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return 0; return 0;
} }
@ -4443,7 +4457,7 @@ PyCurses_ConvertToWchar_t(PyObject *obj,
wchar_t buffer[2]; wchar_t buffer[2];
if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) { if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expect str of length 1 or int, " "expect int or str of length 1, "
"got a str of length %zi", "got a str of length %zi",
PyUnicode_GET_LENGTH(obj)); PyUnicode_GET_LENGTH(obj));
return 0; return 0;
@ -4470,7 +4484,7 @@ PyCurses_ConvertToWchar_t(PyObject *obj,
} }
else { else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"expect str of length 1 or int, got %s", "expect int or str of length 1, got %s",
Py_TYPE(obj)->tp_name); Py_TYPE(obj)->tp_name);
return 0; return 0;
} }

View File

@ -260,20 +260,32 @@ u_getitem(arrayobject *ap, Py_ssize_t i)
static int static int
u_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) u_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
{ {
PyObject *u; if (!PyUnicode_Check(v)) {
if (!PyArg_Parse(v, "U;array item must be unicode character", &u)) { PyErr_Format(PyExc_TypeError,
"array item must be a unicode character, not %T",
v);
return -1; return -1;
} }
Py_ssize_t len = PyUnicode_AsWideChar(u, NULL, 0); Py_ssize_t len = PyUnicode_AsWideChar(v, NULL, 0);
if (len != 2) { if (len != 2) {
PyErr_SetString(PyExc_TypeError, if (PyUnicode_GET_LENGTH(v) != 1) {
"array item must be unicode character"); PyErr_Format(PyExc_TypeError,
"array item must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(v));
}
else {
PyErr_Format(PyExc_TypeError,
"string %A cannot be converted to "
"a single wchar_t character",
v);
}
return -1; return -1;
} }
wchar_t w; wchar_t w;
len = PyUnicode_AsWideChar(u, &w, 1); len = PyUnicode_AsWideChar(v, &w, 1);
assert(len == 1); assert(len == 1);
if (i >= 0) { if (i >= 0) {
@ -291,19 +303,23 @@ w_getitem(arrayobject *ap, Py_ssize_t i)
static int static int
w_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) w_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
{ {
PyObject *u; if (!PyUnicode_Check(v)) {
if (!PyArg_Parse(v, "U;array item must be unicode character", &u)) { PyErr_Format(PyExc_TypeError,
"array item must be a unicode character, not %T",
v);
return -1; return -1;
} }
if (PyUnicode_GetLength(u) != 1) { if (PyUnicode_GET_LENGTH(v) != 1) {
PyErr_SetString(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"array item must be unicode character"); "array item must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(v));
return -1; return -1;
} }
if (i >= 0) { if (i >= 0) {
((Py_UCS4 *)ap->ob_item)[i] = PyUnicode_READ_CHAR(u, 0); ((Py_UCS4 *)ap->ob_item)[i] = PyUnicode_READ_CHAR(v, 0);
} }
return 0; return 0;
} }

View File

@ -234,10 +234,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 1) { if (nargs < 1) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[0]) && PyBytes_GET_SIZE(args[0]) == 1) { if (PyBytes_Check(args[0])) {
if (PyBytes_GET_SIZE(args[0]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 1 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[0]));
goto exit;
}
a = PyBytes_AS_STRING(args[0])[0]; a = PyBytes_AS_STRING(args[0])[0];
} }
else if (PyByteArray_Check(args[0]) && PyByteArray_GET_SIZE(args[0]) == 1) { else if (PyByteArray_Check(args[0])) {
if (PyByteArray_GET_SIZE(args[0]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 1 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[0]));
goto exit;
}
a = PyByteArray_AS_STRING(args[0])[0]; a = PyByteArray_AS_STRING(args[0])[0];
} }
else { else {
@ -247,10 +261,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 2) { if (nargs < 2) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[1]) && PyBytes_GET_SIZE(args[1]) == 1) { if (PyBytes_Check(args[1])) {
if (PyBytes_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 2 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[1]));
goto exit;
}
b = PyBytes_AS_STRING(args[1])[0]; b = PyBytes_AS_STRING(args[1])[0];
} }
else if (PyByteArray_Check(args[1]) && PyByteArray_GET_SIZE(args[1]) == 1) { else if (PyByteArray_Check(args[1])) {
if (PyByteArray_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 2 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[1]));
goto exit;
}
b = PyByteArray_AS_STRING(args[1])[0]; b = PyByteArray_AS_STRING(args[1])[0];
} }
else { else {
@ -260,10 +288,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 3) { if (nargs < 3) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[2]) && PyBytes_GET_SIZE(args[2]) == 1) { if (PyBytes_Check(args[2])) {
if (PyBytes_GET_SIZE(args[2]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 3 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[2]));
goto exit;
}
c = PyBytes_AS_STRING(args[2])[0]; c = PyBytes_AS_STRING(args[2])[0];
} }
else if (PyByteArray_Check(args[2]) && PyByteArray_GET_SIZE(args[2]) == 1) { else if (PyByteArray_Check(args[2])) {
if (PyByteArray_GET_SIZE(args[2]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 3 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[2]));
goto exit;
}
c = PyByteArray_AS_STRING(args[2])[0]; c = PyByteArray_AS_STRING(args[2])[0];
} }
else { else {
@ -273,10 +315,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 4) { if (nargs < 4) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[3]) && PyBytes_GET_SIZE(args[3]) == 1) { if (PyBytes_Check(args[3])) {
if (PyBytes_GET_SIZE(args[3]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 4 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[3]));
goto exit;
}
d = PyBytes_AS_STRING(args[3])[0]; d = PyBytes_AS_STRING(args[3])[0];
} }
else if (PyByteArray_Check(args[3]) && PyByteArray_GET_SIZE(args[3]) == 1) { else if (PyByteArray_Check(args[3])) {
if (PyByteArray_GET_SIZE(args[3]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 4 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[3]));
goto exit;
}
d = PyByteArray_AS_STRING(args[3])[0]; d = PyByteArray_AS_STRING(args[3])[0];
} }
else { else {
@ -286,10 +342,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 5) { if (nargs < 5) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[4]) && PyBytes_GET_SIZE(args[4]) == 1) { if (PyBytes_Check(args[4])) {
if (PyBytes_GET_SIZE(args[4]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 5 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[4]));
goto exit;
}
e = PyBytes_AS_STRING(args[4])[0]; e = PyBytes_AS_STRING(args[4])[0];
} }
else if (PyByteArray_Check(args[4]) && PyByteArray_GET_SIZE(args[4]) == 1) { else if (PyByteArray_Check(args[4])) {
if (PyByteArray_GET_SIZE(args[4]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 5 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[4]));
goto exit;
}
e = PyByteArray_AS_STRING(args[4])[0]; e = PyByteArray_AS_STRING(args[4])[0];
} }
else { else {
@ -299,10 +369,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 6) { if (nargs < 6) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[5]) && PyBytes_GET_SIZE(args[5]) == 1) { if (PyBytes_Check(args[5])) {
if (PyBytes_GET_SIZE(args[5]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 6 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[5]));
goto exit;
}
f = PyBytes_AS_STRING(args[5])[0]; f = PyBytes_AS_STRING(args[5])[0];
} }
else if (PyByteArray_Check(args[5]) && PyByteArray_GET_SIZE(args[5]) == 1) { else if (PyByteArray_Check(args[5])) {
if (PyByteArray_GET_SIZE(args[5]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 6 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[5]));
goto exit;
}
f = PyByteArray_AS_STRING(args[5])[0]; f = PyByteArray_AS_STRING(args[5])[0];
} }
else { else {
@ -312,10 +396,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 7) { if (nargs < 7) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[6]) && PyBytes_GET_SIZE(args[6]) == 1) { if (PyBytes_Check(args[6])) {
if (PyBytes_GET_SIZE(args[6]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 7 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[6]));
goto exit;
}
g = PyBytes_AS_STRING(args[6])[0]; g = PyBytes_AS_STRING(args[6])[0];
} }
else if (PyByteArray_Check(args[6]) && PyByteArray_GET_SIZE(args[6]) == 1) { else if (PyByteArray_Check(args[6])) {
if (PyByteArray_GET_SIZE(args[6]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 7 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[6]));
goto exit;
}
g = PyByteArray_AS_STRING(args[6])[0]; g = PyByteArray_AS_STRING(args[6])[0];
} }
else { else {
@ -325,10 +423,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 8) { if (nargs < 8) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[7]) && PyBytes_GET_SIZE(args[7]) == 1) { if (PyBytes_Check(args[7])) {
if (PyBytes_GET_SIZE(args[7]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 8 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[7]));
goto exit;
}
h = PyBytes_AS_STRING(args[7])[0]; h = PyBytes_AS_STRING(args[7])[0];
} }
else if (PyByteArray_Check(args[7]) && PyByteArray_GET_SIZE(args[7]) == 1) { else if (PyByteArray_Check(args[7])) {
if (PyByteArray_GET_SIZE(args[7]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 8 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[7]));
goto exit;
}
h = PyByteArray_AS_STRING(args[7])[0]; h = PyByteArray_AS_STRING(args[7])[0];
} }
else { else {
@ -338,10 +450,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 9) { if (nargs < 9) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[8]) && PyBytes_GET_SIZE(args[8]) == 1) { if (PyBytes_Check(args[8])) {
if (PyBytes_GET_SIZE(args[8]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 9 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[8]));
goto exit;
}
i = PyBytes_AS_STRING(args[8])[0]; i = PyBytes_AS_STRING(args[8])[0];
} }
else if (PyByteArray_Check(args[8]) && PyByteArray_GET_SIZE(args[8]) == 1) { else if (PyByteArray_Check(args[8])) {
if (PyByteArray_GET_SIZE(args[8]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 9 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[8]));
goto exit;
}
i = PyByteArray_AS_STRING(args[8])[0]; i = PyByteArray_AS_STRING(args[8])[0];
} }
else { else {
@ -351,10 +477,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 10) { if (nargs < 10) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[9]) && PyBytes_GET_SIZE(args[9]) == 1) { if (PyBytes_Check(args[9])) {
if (PyBytes_GET_SIZE(args[9]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 10 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[9]));
goto exit;
}
j = PyBytes_AS_STRING(args[9])[0]; j = PyBytes_AS_STRING(args[9])[0];
} }
else if (PyByteArray_Check(args[9]) && PyByteArray_GET_SIZE(args[9]) == 1) { else if (PyByteArray_Check(args[9])) {
if (PyByteArray_GET_SIZE(args[9]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 10 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[9]));
goto exit;
}
j = PyByteArray_AS_STRING(args[9])[0]; j = PyByteArray_AS_STRING(args[9])[0];
} }
else { else {
@ -364,10 +504,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 11) { if (nargs < 11) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[10]) && PyBytes_GET_SIZE(args[10]) == 1) { if (PyBytes_Check(args[10])) {
if (PyBytes_GET_SIZE(args[10]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 11 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[10]));
goto exit;
}
k = PyBytes_AS_STRING(args[10])[0]; k = PyBytes_AS_STRING(args[10])[0];
} }
else if (PyByteArray_Check(args[10]) && PyByteArray_GET_SIZE(args[10]) == 1) { else if (PyByteArray_Check(args[10])) {
if (PyByteArray_GET_SIZE(args[10]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 11 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[10]));
goto exit;
}
k = PyByteArray_AS_STRING(args[10])[0]; k = PyByteArray_AS_STRING(args[10])[0];
} }
else { else {
@ -377,10 +531,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 12) { if (nargs < 12) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[11]) && PyBytes_GET_SIZE(args[11]) == 1) { if (PyBytes_Check(args[11])) {
if (PyBytes_GET_SIZE(args[11]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 12 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[11]));
goto exit;
}
l = PyBytes_AS_STRING(args[11])[0]; l = PyBytes_AS_STRING(args[11])[0];
} }
else if (PyByteArray_Check(args[11]) && PyByteArray_GET_SIZE(args[11]) == 1) { else if (PyByteArray_Check(args[11])) {
if (PyByteArray_GET_SIZE(args[11]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 12 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[11]));
goto exit;
}
l = PyByteArray_AS_STRING(args[11])[0]; l = PyByteArray_AS_STRING(args[11])[0];
} }
else { else {
@ -390,10 +558,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 13) { if (nargs < 13) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[12]) && PyBytes_GET_SIZE(args[12]) == 1) { if (PyBytes_Check(args[12])) {
if (PyBytes_GET_SIZE(args[12]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 13 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[12]));
goto exit;
}
m = PyBytes_AS_STRING(args[12])[0]; m = PyBytes_AS_STRING(args[12])[0];
} }
else if (PyByteArray_Check(args[12]) && PyByteArray_GET_SIZE(args[12]) == 1) { else if (PyByteArray_Check(args[12])) {
if (PyByteArray_GET_SIZE(args[12]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 13 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[12]));
goto exit;
}
m = PyByteArray_AS_STRING(args[12])[0]; m = PyByteArray_AS_STRING(args[12])[0];
} }
else { else {
@ -403,10 +585,24 @@ char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 14) { if (nargs < 14) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[13]) && PyBytes_GET_SIZE(args[13]) == 1) { if (PyBytes_Check(args[13])) {
if (PyBytes_GET_SIZE(args[13]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 14 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[13]));
goto exit;
}
n = PyBytes_AS_STRING(args[13])[0]; n = PyBytes_AS_STRING(args[13])[0];
} }
else if (PyByteArray_Check(args[13]) && PyByteArray_GET_SIZE(args[13]) == 1) { else if (PyByteArray_Check(args[13])) {
if (PyByteArray_GET_SIZE(args[13]) != 1) {
PyErr_Format(PyExc_TypeError,
"char_converter(): argument 14 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[13]));
goto exit;
}
n = PyByteArray_AS_STRING(args[13])[0]; n = PyByteArray_AS_STRING(args[13])[0];
} }
else { else {
@ -648,7 +844,10 @@ int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(args[2]) != 1) { if (PyUnicode_GET_LENGTH(args[2]) != 1) {
_PyArg_BadArgument("int_converter", "argument 3", "a unicode character", args[2]); PyErr_Format(PyExc_TypeError,
"int_converter(): argument 3 must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(args[2]));
goto exit; goto exit;
} }
c = PyUnicode_READ_CHAR(args[2], 0); c = PyUnicode_READ_CHAR(args[2], 0);
@ -3219,4 +3418,4 @@ _testclinic_TestClass_get_defining_class_arg(PyObject *self, PyTypeObject *cls,
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=aa352c3a67300056 input=a9049054013a1b77]*/ /*[clinic end generated code: output=545d409a47f1826d input=a9049054013a1b77]*/

View File

@ -596,7 +596,10 @@ array__array_reconstructor(PyObject *module, PyObject *const *args, Py_ssize_t n
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(args[1]) != 1) { if (PyUnicode_GET_LENGTH(args[1]) != 1) {
_PyArg_BadArgument("_array_reconstructor", "argument 2", "a unicode character", args[1]); PyErr_Format(PyExc_TypeError,
"_array_reconstructor(): argument 2 must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(args[1]));
goto exit; goto exit;
} }
typecode = PyUnicode_READ_CHAR(args[1], 0); typecode = PyUnicode_READ_CHAR(args[1], 0);
@ -685,4 +688,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__,
#define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \
{"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__},
/*[clinic end generated code: output=52c55d9b1d026c1c input=a9049054013a1b77]*/ /*[clinic end generated code: output=9a3276ffd499c796 input=a9049054013a1b77]*/

View File

@ -36,7 +36,10 @@ unicodedata_UCD_decimal(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(args[0]) != 1) { if (PyUnicode_GET_LENGTH(args[0]) != 1) {
_PyArg_BadArgument("decimal", "argument 1", "a unicode character", args[0]); PyErr_Format(PyExc_TypeError,
"decimal(): argument 1 must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(args[0]));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(args[0], 0); chr = PyUnicode_READ_CHAR(args[0], 0);
@ -82,7 +85,10 @@ unicodedata_UCD_digit(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(args[0]) != 1) { if (PyUnicode_GET_LENGTH(args[0]) != 1) {
_PyArg_BadArgument("digit", "argument 1", "a unicode character", args[0]); PyErr_Format(PyExc_TypeError,
"digit(): argument 1 must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(args[0]));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(args[0], 0); chr = PyUnicode_READ_CHAR(args[0], 0);
@ -129,7 +135,10 @@ unicodedata_UCD_numeric(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(args[0]) != 1) { if (PyUnicode_GET_LENGTH(args[0]) != 1) {
_PyArg_BadArgument("numeric", "argument 1", "a unicode character", args[0]); PyErr_Format(PyExc_TypeError,
"numeric(): argument 1 must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(args[0]));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(args[0], 0); chr = PyUnicode_READ_CHAR(args[0], 0);
@ -167,7 +176,10 @@ unicodedata_UCD_category(PyObject *self, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("category", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"category(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(arg, 0); chr = PyUnicode_READ_CHAR(arg, 0);
@ -202,7 +214,10 @@ unicodedata_UCD_bidirectional(PyObject *self, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("bidirectional", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"bidirectional(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(arg, 0); chr = PyUnicode_READ_CHAR(arg, 0);
@ -238,7 +253,10 @@ unicodedata_UCD_combining(PyObject *self, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("combining", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"combining(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(arg, 0); chr = PyUnicode_READ_CHAR(arg, 0);
@ -279,7 +297,10 @@ unicodedata_UCD_mirrored(PyObject *self, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("mirrored", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"mirrored(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(arg, 0); chr = PyUnicode_READ_CHAR(arg, 0);
@ -316,7 +337,10 @@ unicodedata_UCD_east_asian_width(PyObject *self, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("east_asian_width", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"east_asian_width(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(arg, 0); chr = PyUnicode_READ_CHAR(arg, 0);
@ -351,7 +375,10 @@ unicodedata_UCD_decomposition(PyObject *self, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("decomposition", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"decomposition(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(arg, 0); chr = PyUnicode_READ_CHAR(arg, 0);
@ -473,7 +500,10 @@ unicodedata_UCD_name(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(args[0]) != 1) { if (PyUnicode_GET_LENGTH(args[0]) != 1) {
_PyArg_BadArgument("name", "argument 1", "a unicode character", args[0]); PyErr_Format(PyExc_TypeError,
"name(): argument 1 must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(args[0]));
goto exit; goto exit;
} }
chr = PyUnicode_READ_CHAR(args[0], 0); chr = PyUnicode_READ_CHAR(args[0], 0);
@ -519,4 +549,4 @@ unicodedata_UCD_lookup(PyObject *self, PyObject *arg)
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=ea30f89007b2bfff input=a9049054013a1b77]*/ /*[clinic end generated code: output=8a59d430cee41058 input=a9049054013a1b77]*/

View File

@ -260,7 +260,7 @@ termios_tcsetattr_impl(PyObject *module, int fd, int when, PyObject *term)
} }
else { else {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"tcsetattr: elements of attributes must be characters or integers"); "tcsetattr: elements of attributes must be bytes objects of length 1 or integers");
return NULL; return NULL;
} }
} }

View File

@ -477,21 +477,32 @@ formatlong(PyObject *v, int flags, int prec, int type)
static int static int
byte_converter(PyObject *arg, char *p) byte_converter(PyObject *arg, char *p)
{ {
if (PyBytes_Check(arg) && PyBytes_GET_SIZE(arg) == 1) { if (PyBytes_Check(arg)) {
if (PyBytes_GET_SIZE(arg) != 1) {
PyErr_Format(PyExc_TypeError,
"%%c requires an integer in range(256) or "
"a single byte, not a bytes object of length %zd",
PyBytes_GET_SIZE(arg));
return 0;
}
*p = PyBytes_AS_STRING(arg)[0]; *p = PyBytes_AS_STRING(arg)[0];
return 1; return 1;
} }
else if (PyByteArray_Check(arg) && PyByteArray_GET_SIZE(arg) == 1) { else if (PyByteArray_Check(arg)) {
if (PyByteArray_GET_SIZE(arg) != 1) {
PyErr_Format(PyExc_TypeError,
"%%c requires an integer in range(256) or "
"a single byte, not a bytearray object of length %zd",
PyByteArray_GET_SIZE(arg));
return 0;
}
*p = PyByteArray_AS_STRING(arg)[0]; *p = PyByteArray_AS_STRING(arg)[0];
return 1; return 1;
} }
else { else if (PyIndex_Check(arg)) {
int overflow; int overflow;
long ival = PyLong_AsLongAndOverflow(arg, &overflow); long ival = PyLong_AsLongAndOverflow(arg, &overflow);
if (ival == -1 && PyErr_Occurred()) { if (ival == -1 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
goto onError;
}
return 0; return 0;
} }
if (!(0 <= ival && ival <= 255)) { if (!(0 <= ival && ival <= 255)) {
@ -503,9 +514,9 @@ byte_converter(PyObject *arg, char *p)
*p = (char)ival; *p = (char)ival;
return 1; return 1;
} }
onError: PyErr_Format(PyExc_TypeError,
PyErr_SetString(PyExc_TypeError, "%%c requires an integer in range(256) or a single byte, not %T",
"%c requires an integer in range(256) or a single byte"); arg);
return 0; return 0;
} }

View File

@ -113,10 +113,24 @@ stringlib_ljust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 2) { if (nargs < 2) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[1]) && PyBytes_GET_SIZE(args[1]) == 1) { if (PyBytes_Check(args[1])) {
if (PyBytes_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"ljust(): argument 2 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[1]));
goto exit;
}
fillchar = PyBytes_AS_STRING(args[1])[0]; fillchar = PyBytes_AS_STRING(args[1])[0];
} }
else if (PyByteArray_Check(args[1]) && PyByteArray_GET_SIZE(args[1]) == 1) { else if (PyByteArray_Check(args[1])) {
if (PyByteArray_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"ljust(): argument 2 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[1]));
goto exit;
}
fillchar = PyByteArray_AS_STRING(args[1])[0]; fillchar = PyByteArray_AS_STRING(args[1])[0];
} }
else { else {
@ -169,10 +183,24 @@ stringlib_rjust(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 2) { if (nargs < 2) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[1]) && PyBytes_GET_SIZE(args[1]) == 1) { if (PyBytes_Check(args[1])) {
if (PyBytes_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"rjust(): argument 2 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[1]));
goto exit;
}
fillchar = PyBytes_AS_STRING(args[1])[0]; fillchar = PyBytes_AS_STRING(args[1])[0];
} }
else if (PyByteArray_Check(args[1]) && PyByteArray_GET_SIZE(args[1]) == 1) { else if (PyByteArray_Check(args[1])) {
if (PyByteArray_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"rjust(): argument 2 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[1]));
goto exit;
}
fillchar = PyByteArray_AS_STRING(args[1])[0]; fillchar = PyByteArray_AS_STRING(args[1])[0];
} }
else { else {
@ -225,10 +253,24 @@ stringlib_center(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 2) { if (nargs < 2) {
goto skip_optional; goto skip_optional;
} }
if (PyBytes_Check(args[1]) && PyBytes_GET_SIZE(args[1]) == 1) { if (PyBytes_Check(args[1])) {
if (PyBytes_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"center(): argument 2 must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(args[1]));
goto exit;
}
fillchar = PyBytes_AS_STRING(args[1])[0]; fillchar = PyBytes_AS_STRING(args[1])[0];
} }
else if (PyByteArray_Check(args[1]) && PyByteArray_GET_SIZE(args[1]) == 1) { else if (PyByteArray_Check(args[1])) {
if (PyByteArray_GET_SIZE(args[1]) != 1) {
PyErr_Format(PyExc_TypeError,
"center(): argument 2 must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(args[1]));
goto exit;
}
fillchar = PyByteArray_AS_STRING(args[1])[0]; fillchar = PyByteArray_AS_STRING(args[1])[0];
} }
else { else {
@ -279,4 +321,4 @@ stringlib_zfill(PyObject *self, PyObject *arg)
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=b409bdf9ab68d5a6 input=a9049054013a1b77]*/ /*[clinic end generated code: output=06dd79019356b6bb input=a9049054013a1b77]*/

View File

@ -14057,14 +14057,21 @@ formatchar(PyObject *v)
if (PyUnicode_GET_LENGTH(v) == 1) { if (PyUnicode_GET_LENGTH(v) == 1) {
return PyUnicode_READ_CHAR(v, 0); return PyUnicode_READ_CHAR(v, 0);
} }
goto onError; PyErr_Format(PyExc_TypeError,
"%%c requires an int or a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(v));
return (Py_UCS4) -1;
} }
else { else {
int overflow; int overflow;
long x = PyLong_AsLongAndOverflow(v, &overflow); long x = PyLong_AsLongAndOverflow(v, &overflow);
if (x == -1 && PyErr_Occurred()) { if (x == -1 && PyErr_Occurred()) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) { if (PyErr_ExceptionMatches(PyExc_TypeError)) {
goto onError; PyErr_Format(PyExc_TypeError,
"%%c requires an int or a unicode character, not %T",
v);
return (Py_UCS4) -1;
} }
return (Py_UCS4) -1; return (Py_UCS4) -1;
} }
@ -14078,11 +14085,6 @@ formatchar(PyObject *v)
return (Py_UCS4) x; return (Py_UCS4) x;
} }
onError:
PyErr_SetString(PyExc_TypeError,
"%c requires int or char");
return (Py_UCS4) -1;
} }
/* Parse options of an argument: flags, width, precision. /* Parse options of an argument: flags, width, precision.

View File

@ -355,10 +355,24 @@ msvcrt_putch(PyObject *module, PyObject *arg)
PyObject *return_value = NULL; PyObject *return_value = NULL;
char char_value; char char_value;
if (PyBytes_Check(arg) && PyBytes_GET_SIZE(arg) == 1) { if (PyBytes_Check(arg)) {
if (PyBytes_GET_SIZE(arg) != 1) {
PyErr_Format(PyExc_TypeError,
"putch(): argument must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(arg));
goto exit;
}
char_value = PyBytes_AS_STRING(arg)[0]; char_value = PyBytes_AS_STRING(arg)[0];
} }
else if (PyByteArray_Check(arg) && PyByteArray_GET_SIZE(arg) == 1) { else if (PyByteArray_Check(arg)) {
if (PyByteArray_GET_SIZE(arg) != 1) {
PyErr_Format(PyExc_TypeError,
"putch(): argument must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(arg));
goto exit;
}
char_value = PyByteArray_AS_STRING(arg)[0]; char_value = PyByteArray_AS_STRING(arg)[0];
} }
else { else {
@ -396,7 +410,10 @@ msvcrt_putwch(PyObject *module, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("putwch", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"putwch(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
unicode_char = PyUnicode_READ_CHAR(arg, 0); unicode_char = PyUnicode_READ_CHAR(arg, 0);
@ -430,10 +447,24 @@ msvcrt_ungetch(PyObject *module, PyObject *arg)
PyObject *return_value = NULL; PyObject *return_value = NULL;
char char_value; char char_value;
if (PyBytes_Check(arg) && PyBytes_GET_SIZE(arg) == 1) { if (PyBytes_Check(arg)) {
if (PyBytes_GET_SIZE(arg) != 1) {
PyErr_Format(PyExc_TypeError,
"ungetch(): argument must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE(arg));
goto exit;
}
char_value = PyBytes_AS_STRING(arg)[0]; char_value = PyBytes_AS_STRING(arg)[0];
} }
else if (PyByteArray_Check(arg) && PyByteArray_GET_SIZE(arg) == 1) { else if (PyByteArray_Check(arg)) {
if (PyByteArray_GET_SIZE(arg) != 1) {
PyErr_Format(PyExc_TypeError,
"ungetch(): argument must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE(arg));
goto exit;
}
char_value = PyByteArray_AS_STRING(arg)[0]; char_value = PyByteArray_AS_STRING(arg)[0];
} }
else { else {
@ -471,7 +502,10 @@ msvcrt_ungetwch(PyObject *module, PyObject *arg)
goto exit; goto exit;
} }
if (PyUnicode_GET_LENGTH(arg) != 1) { if (PyUnicode_GET_LENGTH(arg) != 1) {
_PyArg_BadArgument("ungetwch", "argument", "a unicode character", arg); PyErr_Format(PyExc_TypeError,
"ungetwch(): argument must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH(arg));
goto exit; goto exit;
} }
unicode_char = PyUnicode_READ_CHAR(arg, 0); unicode_char = PyUnicode_READ_CHAR(arg, 0);
@ -697,4 +731,4 @@ exit:
#ifndef MSVCRT_GETERRORMODE_METHODDEF #ifndef MSVCRT_GETERRORMODE_METHODDEF
#define MSVCRT_GETERRORMODE_METHODDEF #define MSVCRT_GETERRORMODE_METHODDEF
#endif /* !defined(MSVCRT_GETERRORMODE_METHODDEF) */ #endif /* !defined(MSVCRT_GETERRORMODE_METHODDEF) */
/*[clinic end generated code: output=de9687b46212c2ed input=a9049054013a1b77]*/ /*[clinic end generated code: output=692c6f52bb9193ce input=a9049054013a1b77]*/

View File

@ -589,6 +589,17 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize)
return msgbuf; return msgbuf;
} }
static const char *
convertcharerr(const char *expected, const char *what, Py_ssize_t size,
char *msgbuf, size_t bufsize)
{
assert(expected != NULL);
PyOS_snprintf(msgbuf, bufsize,
"must be %.50s, not %.50s of length %zd",
expected, what, size);
return msgbuf;
}
#define CONV_UNICODE "(unicode conversion error)" #define CONV_UNICODE "(unicode conversion error)"
/* Convert a non-tuple argument. Return NULL if conversion went OK, /* Convert a non-tuple argument. Return NULL if conversion went OK,
@ -795,10 +806,22 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
case 'c': {/* char */ case 'c': {/* char */
char *p = va_arg(*p_va, char *); char *p = va_arg(*p_va, char *);
if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) if (PyBytes_Check(arg)) {
if (PyBytes_GET_SIZE(arg) != 1) {
return convertcharerr("a byte string of length 1",
"a bytes object", PyBytes_GET_SIZE(arg),
msgbuf, bufsize);
}
*p = PyBytes_AS_STRING(arg)[0]; *p = PyBytes_AS_STRING(arg)[0];
else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) }
else if (PyByteArray_Check(arg)) {
if (PyByteArray_GET_SIZE(arg) != 1) {
return convertcharerr("a byte string of length 1",
"a bytearray object", PyByteArray_GET_SIZE(arg),
msgbuf, bufsize);
}
*p = PyByteArray_AS_STRING(arg)[0]; *p = PyByteArray_AS_STRING(arg)[0];
}
else else
return converterr("a byte string of length 1", arg, msgbuf, bufsize); return converterr("a byte string of length 1", arg, msgbuf, bufsize);
break; break;
@ -812,8 +835,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
if (!PyUnicode_Check(arg)) if (!PyUnicode_Check(arg))
return converterr("a unicode character", arg, msgbuf, bufsize); return converterr("a unicode character", arg, msgbuf, bufsize);
if (PyUnicode_GET_LENGTH(arg) != 1) if (PyUnicode_GET_LENGTH(arg) != 1) {
return converterr("a unicode character", arg, msgbuf, bufsize); return convertcharerr("a unicode character",
"a string", PyUnicode_GET_LENGTH(arg),
msgbuf, bufsize);
}
kind = PyUnicode_KIND(arg); kind = PyUnicode_KIND(arg);
data = PyUnicode_DATA(arg); data = PyUnicode_DATA(arg);

View File

@ -89,10 +89,24 @@ class char_converter(CConverter):
def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None: def parse_arg(self, argname: str, displayname: str, *, limited_capi: bool) -> str | None:
if self.format_unit == 'c': if self.format_unit == 'c':
return self.format_code(""" return self.format_code("""
if (PyBytes_Check({argname}) && PyBytes_GET_SIZE({argname}) == 1) {{{{ if (PyBytes_Check({argname})) {{{{
if (PyBytes_GET_SIZE({argname}) != 1) {{{{
PyErr_Format(PyExc_TypeError,
"{{name}}(): {displayname} must be a byte string of length 1, "
"not a bytes object of length %zd",
PyBytes_GET_SIZE({argname}));
goto exit;
}}}}
{paramname} = PyBytes_AS_STRING({argname})[0]; {paramname} = PyBytes_AS_STRING({argname})[0];
}}}} }}}}
else if (PyByteArray_Check({argname}) && PyByteArray_GET_SIZE({argname}) == 1) {{{{ else if (PyByteArray_Check({argname})) {{{{
if (PyByteArray_GET_SIZE({argname}) != 1) {{{{
PyErr_Format(PyExc_TypeError,
"{{name}}(): {displayname} must be a byte string of length 1, "
"not a bytearray object of length %zd",
PyByteArray_GET_SIZE({argname}));
goto exit;
}}}}
{paramname} = PyByteArray_AS_STRING({argname})[0]; {paramname} = PyByteArray_AS_STRING({argname})[0];
}}}} }}}}
else {{{{ else {{{{
@ -101,6 +115,7 @@ class char_converter(CConverter):
}}}} }}}}
""", """,
argname=argname, argname=argname,
displayname=displayname,
bad_argument=self.bad_argument(displayname, 'a byte string of length 1', limited_capi=limited_capi), bad_argument=self.bad_argument(displayname, 'a byte string of length 1', limited_capi=limited_capi),
) )
return super().parse_arg(argname, displayname, limited_capi=limited_capi) return super().parse_arg(argname, displayname, limited_capi=limited_capi)
@ -272,12 +287,16 @@ class int_converter(CConverter):
goto exit; goto exit;
}}}} }}}}
if (PyUnicode_GET_LENGTH({argname}) != 1) {{{{ if (PyUnicode_GET_LENGTH({argname}) != 1) {{{{
{bad_argument} PyErr_Format(PyExc_TypeError,
"{{name}}(): {displayname} must be a unicode character, "
"not a string of length %zd",
PyUnicode_GET_LENGTH({argname}));
goto exit; goto exit;
}}}} }}}}
{paramname} = PyUnicode_READ_CHAR({argname}, 0); {paramname} = PyUnicode_READ_CHAR({argname}, 0);
""", """,
argname=argname, argname=argname,
displayname=displayname,
bad_argument=self.bad_argument(displayname, 'a unicode character', limited_capi=limited_capi), bad_argument=self.bad_argument(displayname, 'a unicode character', limited_capi=limited_capi),
) )
return super().parse_arg(argname, displayname, limited_capi=limited_capi) return super().parse_arg(argname, displayname, limited_capi=limited_capi)