summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-02-11 11:56:17 (GMT)
committerGitHub <noreply@github.com>2024-02-11 11:56:17 (GMT)
commitd8346d6c0677b0e8fcff5aa6b179d3c3afca48c6 (patch)
tree054cc289b1f0ec94e2701855f61a18152c514e4d /Python
parentd65cd8bc4e3a4d070385e2236332c14b63daeada (diff)
downloadcpython-d8346d6c0677b0e8fcff5aa6b179d3c3afca48c6.zip
cpython-d8346d6c0677b0e8fcff5aa6b179d3c3afca48c6.tar.gz
cpython-d8346d6c0677b0e8fcff5aa6b179d3c3afca48c6.tar.bz2
[3.12] gh-115011: Improve support of __index__() in setters of members with unsigned integer type (GH-115029) (GH-115294)
Setters for members with an unsigned integer type now support the same range of valid values for objects that has a __index__() method as for int. Previously, Py_T_UINT, Py_T_ULONG and Py_T_ULLONG did not support objects that has a __index__() method larger than LONG_MAX. Py_T_ULLONG did not support negative ints. Now it supports them and emits a RuntimeWarning. (cherry picked from commit d9d6909697501a2604d5895f9f88aeec61274ab0)
Diffstat (limited to 'Python')
-rw-r--r--Python/structmember.c82
1 files changed, 45 insertions, 37 deletions
diff --git a/Python/structmember.c b/Python/structmember.c
index ebebaa0..f4de0cb 100644
--- a/Python/structmember.c
+++ b/Python/structmember.c
@@ -3,6 +3,9 @@
#include "Python.h"
#include "structmember.h" // PyMemberDef
+#include "pycore_abstract.h" // _PyNumber_Index()
+#include "pycore_long.h" // _PyLong_IsNegative()
+
PyObject *
PyMember_GetOne(const char *obj_addr, PyMemberDef *l)
@@ -200,27 +203,22 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
case 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");
+ v = _PyNumber_Index(v);
+ if (v == NULL) {
return -1;
}
- 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");
+ if (_PyLong_IsNegative((PyLongObject *)v)) {
+ long long_val = PyLong_AsLong(v);
+ Py_DECREF(v);
+ if (long_val == -1 && PyErr_Occurred()) {
+ return -1;
}
+ *(unsigned int *)addr = (unsigned int)(unsigned long)long_val;
+ WARN("Writing negative value into unsigned field");
}
else {
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
+ Py_DECREF(v);
if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
return -1;
}
@@ -240,24 +238,22 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
case 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");
+ v = _PyNumber_Index(v);
+ if (v == NULL) {
return -1;
}
- else if (!overflow) {
- *(unsigned long *)addr = (unsigned long)long_val;
- if (long_val < 0) {
- WARN("Writing negative value into unsigned field");
+ if (_PyLong_IsNegative((PyLongObject *)v)) {
+ long long_val = PyLong_AsLong(v);
+ Py_DECREF(v);
+ if (long_val == -1 && PyErr_Occurred()) {
+ return -1;
}
+ *(unsigned long *)addr = (unsigned long)long_val;
+ WARN("Writing negative value into unsigned field");
}
else {
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
+ Py_DECREF(v);
if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
return -1;
}
@@ -313,18 +309,30 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
return -1;
break;
}
- case T_ULONGLONG:{
- unsigned long long value;
- /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
- doesn't ??? */
- if (PyLong_Check(v))
- *(unsigned long long*)addr = value = PyLong_AsUnsignedLongLong(v);
- else
- *(unsigned long long*)addr = value = PyLong_AsLong(v);
- if ((value == (unsigned long long)-1) && PyErr_Occurred())
+ case Py_T_ULONGLONG: {
+ v = _PyNumber_Index(v);
+ if (v == NULL) {
return -1;
- break;
}
+ if (_PyLong_IsNegative((PyLongObject *)v)) {
+ long long_val = PyLong_AsLong(v);
+ Py_DECREF(v);
+ if (long_val == -1 && PyErr_Occurred()) {
+ return -1;
+ }
+ *(unsigned long long *)addr = (unsigned long long)(long long)long_val;
+ WARN("Writing negative value into unsigned field");
+ }
+ else {
+ unsigned long long ulonglong_val = PyLong_AsUnsignedLongLong(v);
+ Py_DECREF(v);
+ if (ulonglong_val == (unsigned long long)-1 && PyErr_Occurred()) {
+ return -1;
+ }
+ *(unsigned long long*)addr = ulonglong_val;
+ }
+ break;
+ }
default:
PyErr_Format(PyExc_SystemError,
"bad memberdescr type for %s", l->name);