Bug report
PyLong_AsInt32(), PyLong_AsUInt32(), PyLong_AsInt64() and PyLong_AsUInt64() are documented as
Set *value and return 0 on success.
Set an exception and return -1 on error.
but on overflow they write the truncated value into *value before returning -1.
They are implemented on top of PyLong_AsNativeBytes(), which copies the lowest bytes and reports the required size, and the LONG_TO_INT/LONG_TO_UINT macros in Objects/longobject.c only raise OverflowError afterwards:
Py_ssize_t bytes = PyLong_AsNativeBytes(obj, value, sizeof(*value), flags);
if (bytes < 0) {
return -1;
}
if ((size_t)bytes > sizeof(*value)) {
PyErr_SetString(PyExc_OverflowError,
"Python int too large to convert to " type_name);
return -1;
}
This makes the straightforward usage unsafe.
For example, _sqlite3_Cursor_arraysize_set_impl() in Modules/_sqlite/cursor.c passes the target field directly:
import sqlite3
cu = sqlite3.connect(":memory:").cursor()
try:
cu.arraysize = 2**32
except OverflowError:
pass
print(cu.arraysize) # 0, was 1
Either the functions should leave *value unchanged on error, or the documentation should say that its value is unspecified after a failure.
Linked PRs
Bug report
PyLong_AsInt32(),PyLong_AsUInt32(),PyLong_AsInt64()andPyLong_AsUInt64()are documented asbut on overflow they write the truncated value into *value before returning
-1.They are implemented on top of
PyLong_AsNativeBytes(), which copies the lowest bytes and reports the required size, and theLONG_TO_INT/LONG_TO_UINTmacros inObjects/longobject.conly raiseOverflowErrorafterwards:This makes the straightforward usage unsafe.
For example,
_sqlite3_Cursor_arraysize_set_impl()inModules/_sqlite/cursor.cpasses the target field directly:Either the functions should leave *value unchanged on error, or the documentation should say that its value is unspecified after a failure.
Linked PRs