mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	gh-109723: Disable Py_BUILD_CORE in _testcapi (#109727)
Make sure that the internal C API is not tested by mistake by _testcapi. Undefine Py_BUILD_CORE_BUILTIN and Py_BUILD_CORE_MODULE macros in Modules/_testcapi/parts.h: move code from _testcapimodule.c. heaptype_relative.c and vectorcall_limited.c are using the limited C API which is incompatible with the internal C API. Move test_long_numbits() from _testcapi to _testinternalcapi since it uses the internal C API "pycore_long.h". Fix Modules/_testcapi/pyatomic.c: don't include Python.h directly, just include _testcapi/parts.h. Ajust "make check-c-globals" for these changes.
This commit is contained in:
		
							parent
							
								
									c32abf1f21
								
							
						
					
					
						commit
						09a25616a9
					
				
					 8 changed files with 114 additions and 101 deletions
				
			
		
							
								
								
									
										19
									
								
								Modules/_testcapi/clinic/long.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										19
									
								
								Modules/_testcapi/clinic/long.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -133,23 +133,6 @@ _testcapi_test_long_as_double(PyObject *module, PyObject *Py_UNUSED(ignored)) | ||||||
|     return _testcapi_test_long_as_double_impl(module); |     return _testcapi_test_long_as_double_impl(module); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PyDoc_STRVAR(_testcapi_test_long_numbits__doc__, |  | ||||||
| "test_long_numbits($module, /)\n" |  | ||||||
| "--\n" |  | ||||||
| "\n"); |  | ||||||
| 
 |  | ||||||
| #define _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF    \ |  | ||||||
|     {"test_long_numbits", (PyCFunction)_testcapi_test_long_numbits, METH_NOARGS, _testcapi_test_long_numbits__doc__}, |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| _testcapi_test_long_numbits_impl(PyObject *module); |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| _testcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignored)) |  | ||||||
| { |  | ||||||
|     return _testcapi_test_long_numbits_impl(module); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| PyDoc_STRVAR(_testcapi_call_long_compact_api__doc__, | PyDoc_STRVAR(_testcapi_call_long_compact_api__doc__, | ||||||
| "call_long_compact_api($module, arg, /)\n" | "call_long_compact_api($module, arg, /)\n" | ||||||
| "--\n" | "--\n" | ||||||
|  | @ -165,4 +148,4 @@ PyDoc_STRVAR(_testcapi_PyLong_AsInt__doc__, | ||||||
| 
 | 
 | ||||||
| #define _TESTCAPI_PYLONG_ASINT_METHODDEF    \ | #define _TESTCAPI_PYLONG_ASINT_METHODDEF    \ | ||||||
|     {"PyLong_AsInt", (PyCFunction)_testcapi_PyLong_AsInt, METH_O, _testcapi_PyLong_AsInt__doc__}, |     {"PyLong_AsInt", (PyCFunction)_testcapi_PyLong_AsInt, METH_O, _testcapi_PyLong_AsInt__doc__}, | ||||||
| /*[clinic end generated code: output=31267ab2dd90aa1d input=a9049054013a1b77]*/ | /*[clinic end generated code: output=de762870526e241d input=a9049054013a1b77]*/ | ||||||
|  |  | ||||||
|  | @ -4,7 +4,6 @@ | ||||||
| 
 | 
 | ||||||
| #include "parts.h" | #include "parts.h" | ||||||
| #include "clinic/long.c.h" | #include "clinic/long.c.h" | ||||||
| #include "pycore_long.h"          // _PyLong_Sign() |  | ||||||
| 
 | 
 | ||||||
| /*[clinic input]
 | /*[clinic input]
 | ||||||
| module _testcapi | module _testcapi | ||||||
|  | @ -535,57 +534,6 @@ _testcapi_test_long_as_double_impl(PyObject *module) | ||||||
|     return Py_None; |     return Py_None; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*[clinic input]
 |  | ||||||
| _testcapi.test_long_numbits |  | ||||||
| [clinic start generated code]*/ |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| _testcapi_test_long_numbits_impl(PyObject *module) |  | ||||||
| /*[clinic end generated code: output=9eaf8458cb15d7f7 input=265c02d48a13059e]*/ |  | ||||||
| { |  | ||||||
|     struct triple { |  | ||||||
|         long input; |  | ||||||
|         size_t nbits; |  | ||||||
|         int sign; |  | ||||||
|     } testcases[] = {{0, 0, 0}, |  | ||||||
|                      {1L, 1, 1}, |  | ||||||
|                      {-1L, 1, -1}, |  | ||||||
|                      {2L, 2, 1}, |  | ||||||
|                      {-2L, 2, -1}, |  | ||||||
|                      {3L, 2, 1}, |  | ||||||
|                      {-3L, 2, -1}, |  | ||||||
|                      {4L, 3, 1}, |  | ||||||
|                      {-4L, 3, -1}, |  | ||||||
|                      {0x7fffL, 15, 1},          /* one Python int digit */ |  | ||||||
|              {-0x7fffL, 15, -1}, |  | ||||||
|              {0xffffL, 16, 1}, |  | ||||||
|              {-0xffffL, 16, -1}, |  | ||||||
|              {0xfffffffL, 28, 1}, |  | ||||||
|              {-0xfffffffL, 28, -1}}; |  | ||||||
|     size_t i; |  | ||||||
| 
 |  | ||||||
|     for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) { |  | ||||||
|         size_t nbits; |  | ||||||
|         int sign; |  | ||||||
|         PyObject *plong; |  | ||||||
| 
 |  | ||||||
|         plong = PyLong_FromLong(testcases[i].input); |  | ||||||
|         if (plong == NULL) |  | ||||||
|             return NULL; |  | ||||||
|         nbits = _PyLong_NumBits(plong); |  | ||||||
|         sign = _PyLong_Sign(plong); |  | ||||||
| 
 |  | ||||||
|         Py_DECREF(plong); |  | ||||||
|         if (nbits != testcases[i].nbits) |  | ||||||
|             return raiseTestError("test_long_numbits", |  | ||||||
|                             "wrong result for _PyLong_NumBits"); |  | ||||||
|         if (sign != testcases[i].sign) |  | ||||||
|             return raiseTestError("test_long_numbits", |  | ||||||
|                             "wrong result for _PyLong_Sign"); |  | ||||||
|     } |  | ||||||
|     Py_RETURN_NONE; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*[clinic input]
 | /*[clinic input]
 | ||||||
| _testcapi.call_long_compact_api | _testcapi.call_long_compact_api | ||||||
|     arg: object |     arg: object | ||||||
|  | @ -631,7 +579,6 @@ static PyMethodDef test_methods[] = { | ||||||
|     _TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF |     _TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF | ||||||
|     _TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF |     _TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF | ||||||
|     _TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF |     _TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF | ||||||
|     _TESTCAPI_TEST_LONG_NUMBITS_METHODDEF |  | ||||||
|     _TESTCAPI_TEST_LONGLONG_API_METHODDEF |     _TESTCAPI_TEST_LONGLONG_API_METHODDEF | ||||||
|     _TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF |     _TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF | ||||||
|     _TESTCAPI_PYLONG_ASINT_METHODDEF |     _TESTCAPI_PYLONG_ASINT_METHODDEF | ||||||
|  |  | ||||||
|  | @ -4,8 +4,24 @@ | ||||||
| // Always enable assertions
 | // Always enable assertions
 | ||||||
| #undef NDEBUG | #undef NDEBUG | ||||||
| 
 | 
 | ||||||
|  | // The _testcapi extension tests the public C API: header files in Include/ and
 | ||||||
|  | // Include/cpython/ directories. The internal C API must not be tested by
 | ||||||
|  | // _testcapi: use _testinternalcapi for that.
 | ||||||
|  | //
 | ||||||
|  | // _testcapi C files can built with the Py_BUILD_CORE_BUILTIN macro defined if
 | ||||||
|  | // one of the Modules/Setup files asks to build _testcapi as "static"
 | ||||||
|  | // (gh-109723).
 | ||||||
|  | //
 | ||||||
|  | // The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE.
 | ||||||
|  | #undef Py_BUILD_CORE_MODULE | ||||||
|  | #undef Py_BUILD_CORE_BUILTIN | ||||||
|  | 
 | ||||||
| #include "Python.h" | #include "Python.h" | ||||||
| 
 | 
 | ||||||
|  | #ifdef Py_BUILD_CORE | ||||||
|  | #  error "_testcapi must test the public Python C API, not the internal C API" | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| int _PyTestCapi_Init_Vectorcall(PyObject *module); | int _PyTestCapi_Init_Vectorcall(PyObject *module); | ||||||
| int _PyTestCapi_Init_Heaptype(PyObject *module); | int _PyTestCapi_Init_Heaptype(PyObject *module); | ||||||
| int _PyTestCapi_Init_Abstract(PyObject *module); | int _PyTestCapi_Init_Abstract(PyObject *module); | ||||||
|  |  | ||||||
|  | @ -4,10 +4,6 @@ | ||||||
|  * This only tests basic functionality, not any synchronizing ordering. |  * This only tests basic functionality, not any synchronizing ordering. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* Always enable assertions */ |  | ||||||
| #undef NDEBUG |  | ||||||
| 
 |  | ||||||
| #include "Python.h" |  | ||||||
| #include "parts.h" | #include "parts.h" | ||||||
| 
 | 
 | ||||||
| // We define atomic bitwise operations on these types
 | // We define atomic bitwise operations on these types
 | ||||||
|  |  | ||||||
|  | @ -5,19 +5,13 @@ | ||||||
|  * standard Python regression test, via Lib/test/test_capi.py. |  * standard Python regression test, via Lib/test/test_capi.py. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* This module tests the public (Include/ and Include/cpython/) C API.
 | // Include parts.h first since it takes care of NDEBUG and Py_BUILD_CORE macros
 | ||||||
|    The internal C API must not be used here: use _testinternalcapi for that. | // and including Python.h.
 | ||||||
|  | //
 | ||||||
|  | // Several parts of this module are broken out into files in _testcapi/.
 | ||||||
|  | // Include definitions from there.
 | ||||||
|  | #include "_testcapi/parts.h" | ||||||
| 
 | 
 | ||||||
|    The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE |  | ||||||
|    macro defined, but only the public C API must be tested here. */ |  | ||||||
| 
 |  | ||||||
| #undef Py_BUILD_CORE_MODULE |  | ||||||
| #undef Py_BUILD_CORE_BUILTIN |  | ||||||
| 
 |  | ||||||
| /* Always enable assertions */ |  | ||||||
| #undef NDEBUG |  | ||||||
| 
 |  | ||||||
| #include "Python.h" |  | ||||||
| #include "frameobject.h"          // PyFrame_New() | #include "frameobject.h"          // PyFrame_New() | ||||||
| #include "marshal.h"              // PyMarshal_WriteLongToFile() | #include "marshal.h"              // PyMarshal_WriteLongToFile() | ||||||
| 
 | 
 | ||||||
|  | @ -29,17 +23,10 @@ | ||||||
| #  include <sys/wait.h>           // W_STOPCODE
 | #  include <sys/wait.h>           // W_STOPCODE
 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef Py_BUILD_CORE |  | ||||||
| #  error "_testcapi must test the public Python C API, not CPython internal C API" |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifdef bool | #ifdef bool | ||||||
| #  error "The public headers should not include <stdbool.h>, see gh-48924" | #  error "The public headers should not include <stdbool.h>, see gh-48924" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // Several parts of this module are broken out into files in _testcapi/.
 |  | ||||||
| // Include definitions from there.
 |  | ||||||
| #include "_testcapi/parts.h" |  | ||||||
| #include "_testcapi/util.h" | #include "_testcapi/util.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ | ||||||
| #include "pycore_hashtable.h"     // _Py_hashtable_new() | #include "pycore_hashtable.h"     // _Py_hashtable_new() | ||||||
| #include "pycore_initconfig.h"    // _Py_GetConfigsAsDict() | #include "pycore_initconfig.h"    // _Py_GetConfigsAsDict() | ||||||
| #include "pycore_interp.h"        // _PyInterpreterState_GetConfigCopy() | #include "pycore_interp.h"        // _PyInterpreterState_GetConfigCopy() | ||||||
|  | #include "pycore_long.h"          // _PyLong_Sign() | ||||||
| #include "pycore_object.h"        // _PyObject_IsFreed() | #include "pycore_object.h"        // _PyObject_IsFreed() | ||||||
| #include "pycore_pathconfig.h"    // _PyPathConfig_ClearGlobal() | #include "pycore_pathconfig.h"    // _PyPathConfig_ClearGlobal() | ||||||
| #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1() | #include "pycore_pyerrors.h"      // _PyErr_ChainExceptions1() | ||||||
|  | @ -1466,6 +1467,66 @@ _testinternalcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | static PyObject * | ||||||
|  | raiseTestError(const char* test_name, const char* msg) | ||||||
|  | { | ||||||
|  |     PyErr_Format(PyExc_AssertionError, "%s: %s", test_name, msg); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*[clinic input]
 | ||||||
|  | _testinternalcapi.test_long_numbits | ||||||
|  | [clinic start generated code]*/ | ||||||
|  | 
 | ||||||
|  | static PyObject * | ||||||
|  | _testinternalcapi_test_long_numbits_impl(PyObject *module) | ||||||
|  | /*[clinic end generated code: output=745d62d120359434 input=f14ca6f638e44dad]*/ | ||||||
|  | { | ||||||
|  |     struct triple { | ||||||
|  |         long input; | ||||||
|  |         size_t nbits; | ||||||
|  |         int sign; | ||||||
|  |     } testcases[] = {{0, 0, 0}, | ||||||
|  |                      {1L, 1, 1}, | ||||||
|  |                      {-1L, 1, -1}, | ||||||
|  |                      {2L, 2, 1}, | ||||||
|  |                      {-2L, 2, -1}, | ||||||
|  |                      {3L, 2, 1}, | ||||||
|  |                      {-3L, 2, -1}, | ||||||
|  |                      {4L, 3, 1}, | ||||||
|  |                      {-4L, 3, -1}, | ||||||
|  |                      {0x7fffL, 15, 1},          /* one Python int digit */ | ||||||
|  |              {-0x7fffL, 15, -1}, | ||||||
|  |              {0xffffL, 16, 1}, | ||||||
|  |              {-0xffffL, 16, -1}, | ||||||
|  |              {0xfffffffL, 28, 1}, | ||||||
|  |              {-0xfffffffL, 28, -1}}; | ||||||
|  |     size_t i; | ||||||
|  | 
 | ||||||
|  |     for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) { | ||||||
|  |         size_t nbits; | ||||||
|  |         int sign; | ||||||
|  |         PyObject *plong; | ||||||
|  | 
 | ||||||
|  |         plong = PyLong_FromLong(testcases[i].input); | ||||||
|  |         if (plong == NULL) | ||||||
|  |             return NULL; | ||||||
|  |         nbits = _PyLong_NumBits(plong); | ||||||
|  |         sign = _PyLong_Sign(plong); | ||||||
|  | 
 | ||||||
|  |         Py_DECREF(plong); | ||||||
|  |         if (nbits != testcases[i].nbits) | ||||||
|  |             return raiseTestError("test_long_numbits", | ||||||
|  |                             "wrong result for _PyLong_NumBits"); | ||||||
|  |         if (sign != testcases[i].sign) | ||||||
|  |             return raiseTestError("test_long_numbits", | ||||||
|  |                             "wrong result for _PyLong_Sign"); | ||||||
|  |     } | ||||||
|  |     Py_RETURN_NONE; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| static PyMethodDef module_functions[] = { | static PyMethodDef module_functions[] = { | ||||||
|     {"get_configs", get_configs, METH_NOARGS}, |     {"get_configs", get_configs, METH_NOARGS}, | ||||||
|     {"get_recursion_depth", get_recursion_depth, METH_NOARGS}, |     {"get_recursion_depth", get_recursion_depth, METH_NOARGS}, | ||||||
|  | @ -1521,6 +1582,7 @@ static PyMethodDef module_functions[] = { | ||||||
|      _PyCFunction_CAST(run_in_subinterp_with_config), |      _PyCFunction_CAST(run_in_subinterp_with_config), | ||||||
|      METH_VARARGS | METH_KEYWORDS}, |      METH_VARARGS | METH_KEYWORDS}, | ||||||
|     _TESTINTERNALCAPI_WRITE_UNRAISABLE_EXC_METHODDEF |     _TESTINTERNALCAPI_WRITE_UNRAISABLE_EXC_METHODDEF | ||||||
|  |     _TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF | ||||||
|     {NULL, NULL} /* sentinel */ |     {NULL, NULL} /* sentinel */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								Modules/clinic/_testinternalcapi.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										19
									
								
								Modules/clinic/_testinternalcapi.c.h
									
										
									
										generated
									
									
									
								
							|  | @ -296,4 +296,21 @@ _testinternalcapi_write_unraisable_exc(PyObject *module, PyObject *const *args, | ||||||
| exit: | exit: | ||||||
|     return return_value; |     return return_value; | ||||||
| } | } | ||||||
| /*[clinic end generated code: output=c7156622e80df1ce input=a9049054013a1b77]*/ | 
 | ||||||
|  | PyDoc_STRVAR(_testinternalcapi_test_long_numbits__doc__, | ||||||
|  | "test_long_numbits($module, /)\n" | ||||||
|  | "--\n" | ||||||
|  | "\n"); | ||||||
|  | 
 | ||||||
|  | #define _TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF    \ | ||||||
|  |     {"test_long_numbits", (PyCFunction)_testinternalcapi_test_long_numbits, METH_NOARGS, _testinternalcapi_test_long_numbits__doc__}, | ||||||
|  | 
 | ||||||
|  | static PyObject * | ||||||
|  | _testinternalcapi_test_long_numbits_impl(PyObject *module); | ||||||
|  | 
 | ||||||
|  | static PyObject * | ||||||
|  | _testinternalcapi_test_long_numbits(PyObject *module, PyObject *Py_UNUSED(ignored)) | ||||||
|  | { | ||||||
|  |     return _testinternalcapi_test_long_numbits_impl(module); | ||||||
|  | } | ||||||
|  | /*[clinic end generated code: output=59144f59957627bd input=a9049054013a1b77]*/ | ||||||
|  |  | ||||||
|  | @ -3,18 +3,20 @@ | ||||||
| 
 | 
 | ||||||
| from . import common as _common | from . import common as _common | ||||||
| 
 | 
 | ||||||
| # The following C files define the Py_LIMITED_API macro, and so must not be | # The following C files must not built with Py_BUILD_CORE. | ||||||
| # built with the Py_BUILD_CORE macro defined. | FILES_WITHOUT_INTERNAL_CAPI = frozenset(( | ||||||
| USE_LIMITED_C_API = frozenset(( |  | ||||||
|     # Modules/ |     # Modules/ | ||||||
|     '_testcapimodule.c', |     '_testcapimodule.c', | ||||||
|     '_testclinic_limited.c', |     '_testclinic_limited.c', | ||||||
|     'xxlimited.c', |     'xxlimited.c', | ||||||
|     'xxlimited_35.c', |     'xxlimited_35.c', | ||||||
|  | )) | ||||||
| 
 | 
 | ||||||
|  | # C files in the fhe following directories must not be built with | ||||||
|  | # Py_BUILD_CORE. | ||||||
|  | DIRS_WITHOUT_INTERNAL_CAPI = frozenset(( | ||||||
|     # Modules/_testcapi/ |     # Modules/_testcapi/ | ||||||
|     'heaptype_relative.c', |     '_testcapi', | ||||||
|     'vectorcall_limited.c', |  | ||||||
| )) | )) | ||||||
| 
 | 
 | ||||||
| TOOL = 'gcc' | TOOL = 'gcc' | ||||||
|  | @ -75,7 +77,10 @@ def preprocess(filename, | ||||||
|     filename = _normpath(filename, cwd) |     filename = _normpath(filename, cwd) | ||||||
| 
 | 
 | ||||||
|     postargs = POST_ARGS |     postargs = POST_ARGS | ||||||
|     if os.path.basename(filename) not in USE_LIMITED_C_API: |     basename = os.path.basename(filename) | ||||||
|  |     dirname = os.path.basename(os.path.dirname(filename)) | ||||||
|  |     if (basename not in FILES_WITHOUT_INTERNAL_CAPI | ||||||
|  |        and dirname not in DIRS_WITHOUT_INTERNAL_CAPI): | ||||||
|         postargs += ('-DPy_BUILD_CORE=1',) |         postargs += ('-DPy_BUILD_CORE=1',) | ||||||
| 
 | 
 | ||||||
|     text = _common.preprocess( |     text = _common.preprocess( | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner