gh-114388: Fix warnings when assign an unsigned integer member (GH-114391)

* Fix a RuntimeWarning emitted when assign an integer-like value that
  is not an instance of int to an attribute that corresponds to a C
  struct member of type T_UINT and T_ULONG.
* Fix a double RuntimeWarning emitted when assign a negative integer value
  to an attribute that corresponds to a C struct member of type T_UINT.
This commit is contained in:
Serhiy Storchaka 2024-02-04 17:32:25 +02:00 committed by GitHub
parent 0ea366240b
commit 3ddc515255
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 98 additions and 29 deletions

View file

@ -197,45 +197,72 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
WARN("Truncation of value to int");
break;
}
case Py_T_UINT:{
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
ulong_val = PyLong_AsLong(v);
if ((ulong_val == (unsigned long)-1) &&
PyErr_Occurred())
return -1;
*(unsigned int *)addr = (unsigned int)ulong_val;
WARN("Writing negative value into unsigned field");
} else
*(unsigned int *)addr = (unsigned int)ulong_val;
if (ulong_val > UINT_MAX)
WARN("Truncation of value to unsigned int");
break;
case Py_T_UINT: {
/* XXX: For compatibility, accept negative int values
as well. */
int overflow;
long long_val = PyLong_AsLongAndOverflow(v, &overflow);
if (long_val == -1 && PyErr_Occurred()) {
return -1;
}
if (overflow < 0) {
PyErr_SetString(PyExc_OverflowError,
"Python int too large to convert to C long");
}
else if (!overflow) {
*(unsigned int *)addr = (unsigned int)(unsigned long)long_val;
if (long_val < 0) {
WARN("Writing negative value into unsigned field");
}
else if ((unsigned long)long_val > UINT_MAX) {
WARN("Truncation of value to unsigned short");
}
}
else {
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
return -1;
}
*(unsigned int*)addr = (unsigned int)ulong_val;
if (ulong_val > UINT_MAX) {
WARN("Truncation of value to unsigned int");
}
}
break;
}
case Py_T_LONG:{
*(long*)addr = PyLong_AsLong(v);
if ((*(long*)addr == -1) && PyErr_Occurred())
return -1;
break;
}
case Py_T_ULONG:{
*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
if ((*(unsigned long*)addr == (unsigned long)-1)
&& PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
*(unsigned long*)addr = PyLong_AsLong(v);
if ((*(unsigned long*)addr == (unsigned long)-1)
&& PyErr_Occurred())
case Py_T_ULONG: {
/* XXX: For compatibility, accept negative int values
as well. */
int overflow;
long long_val = PyLong_AsLongAndOverflow(v, &overflow);
if (long_val == -1 && PyErr_Occurred()) {
return -1;
}
if (overflow < 0) {
PyErr_SetString(PyExc_OverflowError,
"Python int too large to convert to C long");
}
else if (!overflow) {
*(unsigned long *)addr = (unsigned long)long_val;
if (long_val < 0) {
WARN("Writing negative value into unsigned field");
}
}
else {
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
return -1;
WARN("Writing negative value into unsigned field");
}
*(unsigned long*)addr = ulong_val;
}
break;
}
}
case Py_T_PYSSIZET:{
*(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)