From c55e73112c7b0574d05a522015d0c927de266525 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Aug 2023 18:53:50 +0200 Subject: [PATCH] gh-106320: Remove private PyLong C API functions (#108429) Remove private PyLong C API functions: * _PyLong_AsByteArray() * _PyLong_DivmodNear() * _PyLong_Format() * _PyLong_Frexp() * _PyLong_FromByteArray() * _PyLong_FromBytes() * _PyLong_GCD() * _PyLong_Lshift() * _PyLong_Rshift() Move these functions to the internal C API. No longer export _PyLong_FromBytes() function. --- Include/cpython/longobject.h | 70 +------------------------ Include/internal/pycore_long.h | 84 ++++++++++++++++++++++++++++-- Modules/_io/_iomodule.c | 5 +- Modules/_pickle.c | 1 + Modules/_randommodule.c | 2 +- Modules/_sqlite/util.c | 5 ++ Modules/_struct.c | 1 + Modules/arraymodule.c | 5 +- Modules/cjkcodecs/multibytecodec.c | 1 + Python/hamt.c | 5 +- 10 files changed, 100 insertions(+), 79 deletions(-) diff --git a/Include/cpython/longobject.h b/Include/cpython/longobject.h index 90cc0f267ae..c581f51cbcd 100644 --- a/Include/cpython/longobject.h +++ b/Include/cpython/longobject.h @@ -10,16 +10,7 @@ PyAPI_FUNC(int) _PyLong_UnsignedLong_Converter(PyObject *, void *); PyAPI_FUNC(int) _PyLong_UnsignedLongLong_Converter(PyObject *, void *); PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *); -/* _PyLong_Frexp returns a double x and an exponent e such that the - true value is approximately equal to x * 2**e. e is >= 0. x is - 0.0 if and only if the input is 0 (in which case, e and x are both - zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is - possible if the number of bits doesn't fit into a Py_ssize_t, sets - OverflowError and returns -1.0 for x, 0 for e. */ -PyAPI_FUNC(double) _PyLong_Frexp(PyLongObject *a, Py_ssize_t *e); - -PyAPI_FUNC(PyObject *) PyLong_FromUnicodeObject(PyObject *u, int base); -PyAPI_FUNC(PyObject *) _PyLong_FromBytes(const char *, Py_ssize_t, int); +PyAPI_FUNC(PyObject*) PyLong_FromUnicodeObject(PyObject *u, int base); /* _PyLong_Sign. Return 0 if v is 0, -1 if v < 0, +1 if v > 0. v must not be NULL, and must be a normalized long. @@ -36,65 +27,6 @@ PyAPI_FUNC(int) _PyLong_Sign(PyObject *v); */ PyAPI_FUNC(size_t) _PyLong_NumBits(PyObject *v); -/* _PyLong_DivmodNear. Given integers a and b, compute the nearest - integer q to the exact quotient a / b, rounding to the nearest even integer - in the case of a tie. Return (q, r), where r = a - q*b. The remainder r - will satisfy abs(r) <= abs(b)/2, with equality possible only if q is - even. -*/ -PyAPI_FUNC(PyObject *) _PyLong_DivmodNear(PyObject *, PyObject *); - -/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in - base 256, and return a Python int with the same numeric value. - If n is 0, the integer is 0. Else: - If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; - else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the - LSB. - If is_signed is 0/false, view the bytes as a non-negative integer. - If is_signed is 1/true, view the bytes as a 2's-complement integer, - non-negative if bit 0x80 of the MSB is clear, negative if set. - Error returns: - + Return NULL with the appropriate exception set if there's not - enough memory to create the Python int. -*/ -PyAPI_FUNC(PyObject *) _PyLong_FromByteArray( - const unsigned char* bytes, size_t n, - int little_endian, int is_signed); - -/* _PyLong_AsByteArray: Convert the least-significant 8*n bits of long - v to a base-256 integer, stored in array bytes. Normally return 0, - return -1 on error. - If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at - bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and - the LSB at bytes[n-1]. - If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes - are filled and there's nothing special about bit 0x80 of the MSB. - If is_signed is 1/true, bytes is filled with the 2's-complement - representation of v's value. Bit 0x80 of the MSB is the sign bit. - Error returns (-1): - + is_signed is 0 and v < 0. TypeError is set in this case, and bytes - isn't altered. - + n isn't big enough to hold the full mathematical value of v. For - example, if is_signed is 0 and there are more digits in the v than - fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of - being large enough to hold a sign bit. OverflowError is set in this - case, but bytes holds the least-significant n bytes of the true value. -*/ -PyAPI_FUNC(int) _PyLong_AsByteArray(PyLongObject* v, - unsigned char* bytes, size_t n, - int little_endian, int is_signed); - -/* _PyLong_Format: Convert the long to a string object with given base, - appending a base prefix of 0[box] if base is 2, 8 or 16. */ -PyAPI_FUNC(PyObject *) _PyLong_Format(PyObject *obj, int base); - -/* For use by the gcd function in mathmodule.c */ -PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *); - -PyAPI_FUNC(PyObject *) _PyLong_Rshift(PyObject *, size_t); -PyAPI_FUNC(PyObject *) _PyLong_Lshift(PyObject *, size_t); - - PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op); PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op); diff --git a/Include/internal/pycore_long.h b/Include/internal/pycore_long.h index 4eb70f7e370..a76494808bf 100644 --- a/Include/internal/pycore_long.h +++ b/Include/internal/pycore_long.h @@ -79,9 +79,87 @@ static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i) return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i]; } -extern PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right); -extern PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right); -extern PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right); +// _PyLong_Frexp returns a double x and an exponent e such that the +// true value is approximately equal to x * 2**e. e is >= 0. x is +// 0.0 if and only if the input is 0 (in which case, e and x are both +// zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is +// possible if the number of bits doesn't fit into a Py_ssize_t, sets +// OverflowError and returns -1.0 for x, 0 for e. +// +// Export for 'math' shared extension +PyAPI_DATA(double) _PyLong_Frexp(PyLongObject *a, Py_ssize_t *e); + +extern PyObject* _PyLong_FromBytes(const char *, Py_ssize_t, int); + +// _PyLong_DivmodNear. Given integers a and b, compute the nearest +// integer q to the exact quotient a / b, rounding to the nearest even integer +// in the case of a tie. Return (q, r), where r = a - q*b. The remainder r +// will satisfy abs(r) <= abs(b)/2, with equality possible only if q is +// even. +// +// Export for '_datetime' shared extension. +PyAPI_DATA(PyObject*) _PyLong_DivmodNear(PyObject *, PyObject *); + +// _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in +// base 256, and return a Python int with the same numeric value. +// If n is 0, the integer is 0. Else: +// If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; +// else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the +// LSB. +// If is_signed is 0/false, view the bytes as a non-negative integer. +// If is_signed is 1/true, view the bytes as a 2's-complement integer, +// non-negative if bit 0x80 of the MSB is clear, negative if set. +// Error returns: +// + Return NULL with the appropriate exception set if there's not +// enough memory to create the Python int. +// +// Export for '_multibytecodec' shared extension. +PyAPI_DATA(PyObject*) _PyLong_FromByteArray( + const unsigned char* bytes, size_t n, + int little_endian, int is_signed); + +// _PyLong_AsByteArray: Convert the least-significant 8*n bits of long +// v to a base-256 integer, stored in array bytes. Normally return 0, +// return -1 on error. +// If little_endian is 1/true, store the MSB at bytes[n-1] and the LSB at +// bytes[0]; else (little_endian is 0/false) store the MSB at bytes[0] and +// the LSB at bytes[n-1]. +// If is_signed is 0/false, it's an error if v < 0; else (v >= 0) n bytes +// are filled and there's nothing special about bit 0x80 of the MSB. +// If is_signed is 1/true, bytes is filled with the 2's-complement +// representation of v's value. Bit 0x80 of the MSB is the sign bit. +// Error returns (-1): +// + is_signed is 0 and v < 0. TypeError is set in this case, and bytes +// isn't altered. +// + n isn't big enough to hold the full mathematical value of v. For +// example, if is_signed is 0 and there are more digits in the v than +// fit in n; or if is_signed is 1, v < 0, and n is just 1 bit shy of +// being large enough to hold a sign bit. OverflowError is set in this +// case, but bytes holds the least-significant n bytes of the true value. +// +// Export for '_struct' shared extension. +PyAPI_DATA(int) _PyLong_AsByteArray(PyLongObject* v, + unsigned char* bytes, size_t n, + int little_endian, int is_signed); + +// _PyLong_Format: Convert the long to a string object with given base, +// appending a base prefix of 0[box] if base is 2, 8 or 16. +// Export for '_tkinter' shared extension. +PyAPI_DATA(PyObject*) _PyLong_Format(PyObject *obj, int base); + +// For use by the math.gcd() function. +// Export for 'math' shared extension. +PyAPI_DATA(PyObject*) _PyLong_GCD(PyObject *, PyObject *); + +// Export for 'math' shared extension +PyAPI_DATA(PyObject*) _PyLong_Rshift(PyObject *, size_t); + +// Export for 'math' shared extension +PyAPI_DATA(PyObject*) _PyLong_Lshift(PyObject *, size_t); + +extern PyObject* _PyLong_Add(PyLongObject *left, PyLongObject *right); +extern PyObject* _PyLong_Multiply(PyLongObject *left, PyLongObject *right); +extern PyObject* _PyLong_Subtract(PyLongObject *left, PyLongObject *right); // Export for 'binascii' shared extension. PyAPI_DATA(unsigned char) _PyLong_DigitValue[256]; diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1a7920eebe0..f56654227f1 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -8,9 +8,10 @@ */ #include "Python.h" -#include "_iomodule.h" -#include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_pystate.h" // _PyInterpreterState_GET() + +#include "_iomodule.h" #ifdef HAVE_SYS_TYPES_H #include diff --git a/Modules/_pickle.c b/Modules/_pickle.c index c2b04cc513a..4f26ffe27d7 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -11,6 +11,7 @@ #include "Python.h" #include "pycore_bytesobject.h" // _PyBytesWriter #include "pycore_ceval.h" // _Py_EnterRecursiveCall() +#include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_object.h" // _PyNone_Type #include "pycore_pystate.h" // _PyThreadState_GET() diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 7daa1f93279..18811d03adb 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -71,9 +71,9 @@ #endif #include "Python.h" +#include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pylifecycle.h" // _PyOS_URandomNonblock() -#include "pycore_runtime.h" #ifdef HAVE_PROCESS_H # include // getpid() #endif diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index 2b3bbfefa3c..833a666301d 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -21,7 +21,12 @@ * 3. This notice may not be removed or altered from any source distribution. */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "module.h" +#include "pycore_long.h" // _PyLong_AsByteArray() #include "connection.h" // Returns non-NULL if a new exception should be raised diff --git a/Modules/_struct.c b/Modules/_struct.c index 425715ad030..606ae5e4e19 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -9,6 +9,7 @@ #include "Python.h" #include "pycore_bytesobject.h" // _PyBytesWriter +#include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() #include diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index a40a5b75b63..5c1e6cb9cff 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -8,9 +8,10 @@ #endif #include "Python.h" -#include "pycore_call.h" // _PyObject_CallMethod() -#include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_bytesobject.h" // _PyBytes_Repeat +#include "pycore_call.h" // _PyObject_CallMethod() +#include "pycore_long.h" // _PyLong_FromByteArray() +#include "pycore_moduleobject.h" // _PyModule_GetState() #include // offsetof() #include diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c index 5d3c16a9842..7c1da900454 100644 --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -9,6 +9,7 @@ #endif #include "Python.h" +#include "pycore_long.h" // _PyLong_FromByteArray() #include "multibytecodec.h" #include "clinic/multibytecodec.c.h" diff --git a/Python/hamt.c b/Python/hamt.c index 24265edc2c3..a8fbb00b807 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -1,9 +1,10 @@ #include "Python.h" - -#include "pycore_bitutils.h" // _Py_popcount32 +#include "pycore_bitutils.h" // _Py_popcount32() #include "pycore_hamt.h" #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_long.h" // _PyLong_Format() #include "pycore_object.h" // _PyObject_GC_TRACK() + #include // offsetof() /*