gh-156101: Don't set the result in error in PyLong_AsInt32() (#156727)
Don't set the result in error in PyLong_AsInt32(), PyLong_AsUInt32(),
PyLong_AsInt64() and PyLong_AsUInt64(). Leave the result unchanged in
this case.
diff --git a/Misc/NEWS.d/next/C_API/2026-08-31-19-14-15.gh-issue-156101.d4PSIF.rst b/Misc/NEWS.d/next/C_API/2026-08-31-19-14-15.gh-issue-156101.d4PSIF.rst
new file mode 100644
index 0000000..68822d6
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2026-08-31-19-14-15.gh-issue-156101.d4PSIF.rst
@@ -0,0 +1,4 @@
+Don't set the result in error in :c:func:`PyLong_AsInt32`,
+:c:func:`PyLong_AsUInt32`, :c:func:`PyLong_AsInt64` and
+:c:func:`PyLong_AsUInt64`. Leave the result unchanged in this case. Patch by
+Victor Stinner.
diff --git a/Modules/_testlimitedcapi/long.c b/Modules/_testlimitedcapi/long.c
index 7c6928d..1654f92 100644
--- a/Modules/_testlimitedcapi/long.c
+++ b/Modules/_testlimitedcapi/long.c
@@ -764,8 +764,9 @@ static PyObject *
pylong_asint32(PyObject *module, PyObject *arg)
{
NULLABLE(arg);
- int32_t value;
+ int32_t value = UNINITIALIZED_INT;
if (PyLong_AsInt32(arg, &value) < 0) {
+ assert(value == UNINITIALIZED_INT);
return NULL;
}
return PyLong_FromInt32(value);
@@ -775,8 +776,9 @@ static PyObject *
pylong_asuint32(PyObject *module, PyObject *arg)
{
NULLABLE(arg);
- uint32_t value;
+ uint32_t value = UNINITIALIZED_INT;
if (PyLong_AsUInt32(arg, &value) < 0) {
+ assert(value == UNINITIALIZED_INT);
return NULL;
}
return PyLong_FromUInt32(value);
@@ -787,8 +789,9 @@ static PyObject *
pylong_asint64(PyObject *module, PyObject *arg)
{
NULLABLE(arg);
- int64_t value;
+ int64_t value = UNINITIALIZED_INT;
if (PyLong_AsInt64(arg, &value) < 0) {
+ assert(value == UNINITIALIZED_INT);
return NULL;
}
return PyLong_FromInt64(value);
@@ -798,8 +801,9 @@ static PyObject *
pylong_asuint64(PyObject *module, PyObject *arg)
{
NULLABLE(arg);
- uint64_t value;
+ uint64_t value = UNINITIALIZED_INT;
if (PyLong_AsUInt64(arg, &value) < 0) {
+ assert(value == UNINITIALIZED_INT);
return NULL;
}
return PyLong_FromUInt64(value);
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 7a38ae8..6454565 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -6800,58 +6800,62 @@ PyObject* PyLong_FromUInt64(uint64_t value)
PYLONG_FROM_UINT(uint64_t, value);
}
-#define LONG_TO_INT(obj, value, type_name) \
+#define LONG_TO_INT(type, obj, result) \
do { \
+ type value; \
int flags = (Py_ASNATIVEBYTES_NATIVE_ENDIAN \
| Py_ASNATIVEBYTES_ALLOW_INDEX); \
- Py_ssize_t bytes = PyLong_AsNativeBytes(obj, value, sizeof(*value), flags); \
+ Py_ssize_t bytes = PyLong_AsNativeBytes(obj, &value, sizeof(value), flags); \
if (bytes < 0) { \
return -1; \
} \
- if ((size_t)bytes > sizeof(*value)) { \
+ if ((size_t)bytes > sizeof(value)) { \
PyErr_SetString(PyExc_OverflowError, \
- "Python int too large to convert to " type_name); \
+ "Python int too large to convert to C " #type); \
return -1; \
} \
+ *result = value; \
return 0; \
} while (0)
-int PyLong_AsInt32(PyObject *obj, int32_t *value)
+int PyLong_AsInt32(PyObject *obj, int32_t *result)
{
- LONG_TO_INT(obj, value, "C int32_t");
+ LONG_TO_INT(int32_t, obj, result);
}
-int PyLong_AsInt64(PyObject *obj, int64_t *value)
+int PyLong_AsInt64(PyObject *obj, int64_t *result)
{
- LONG_TO_INT(obj, value, "C int64_t");
+ LONG_TO_INT(int64_t, obj, result);
}
-#define LONG_TO_UINT(obj, value, type_name) \
+#define LONG_TO_UINT(type, obj, result) \
do { \
+ type value; \
int flags = (Py_ASNATIVEBYTES_NATIVE_ENDIAN \
| Py_ASNATIVEBYTES_UNSIGNED_BUFFER \
| Py_ASNATIVEBYTES_REJECT_NEGATIVE \
| Py_ASNATIVEBYTES_ALLOW_INDEX); \
- Py_ssize_t bytes = PyLong_AsNativeBytes(obj, value, sizeof(*value), flags); \
+ Py_ssize_t bytes = PyLong_AsNativeBytes(obj, &value, sizeof(value), flags); \
if (bytes < 0) { \
return -1; \
} \
- if ((size_t)bytes > sizeof(*value)) { \
+ if ((size_t)bytes > sizeof(value)) { \
PyErr_SetString(PyExc_OverflowError, \
- "Python int too large to convert to " type_name); \
+ "Python int too large to convert to C " #type); \
return -1; \
} \
+ *result = value; \
return 0; \
} while (0)
-int PyLong_AsUInt32(PyObject *obj, uint32_t *value)
+int PyLong_AsUInt32(PyObject *obj, uint32_t *result)
{
- LONG_TO_UINT(obj, value, "C uint32_t");
+ LONG_TO_UINT(uint32_t, obj, result);
}
-int PyLong_AsUInt64(PyObject *obj, uint64_t *value)
+int PyLong_AsUInt64(PyObject *obj, uint64_t *result)
{
- LONG_TO_UINT(obj, value, "C uint64_t");
+ LONG_TO_UINT(uint64_t, obj, result);
}