Skip to content

Commit 1c4058c

Browse files
vstinnerGlyphack
authored andcommitted
pythongh-109723: Disable Py_BUILD_CORE in _testcapi (python#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.
1 parent a2697d0 commit 1c4058c

File tree

8 files changed

+114
-101
lines changed

8 files changed

+114
-101
lines changed

Modules/_testcapi/clinic/long.c.h

+1-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/_testcapi/long.c

-53
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
#include "parts.h"
66
#include "clinic/long.c.h"
7-
#include "pycore_long.h" // _PyLong_Sign()
87

98
/*[clinic input]
109
module _testcapi
@@ -535,57 +534,6 @@ _testcapi_test_long_as_double_impl(PyObject *module)
535534
return Py_None;
536535
}
537536

538-
/*[clinic input]
539-
_testcapi.test_long_numbits
540-
[clinic start generated code]*/
541-
542-
static PyObject *
543-
_testcapi_test_long_numbits_impl(PyObject *module)
544-
/*[clinic end generated code: output=9eaf8458cb15d7f7 input=265c02d48a13059e]*/
545-
{
546-
struct triple {
547-
long input;
548-
size_t nbits;
549-
int sign;
550-
} testcases[] = {{0, 0, 0},
551-
{1L, 1, 1},
552-
{-1L, 1, -1},
553-
{2L, 2, 1},
554-
{-2L, 2, -1},
555-
{3L, 2, 1},
556-
{-3L, 2, -1},
557-
{4L, 3, 1},
558-
{-4L, 3, -1},
559-
{0x7fffL, 15, 1}, /* one Python int digit */
560-
{-0x7fffL, 15, -1},
561-
{0xffffL, 16, 1},
562-
{-0xffffL, 16, -1},
563-
{0xfffffffL, 28, 1},
564-
{-0xfffffffL, 28, -1}};
565-
size_t i;
566-
567-
for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) {
568-
size_t nbits;
569-
int sign;
570-
PyObject *plong;
571-
572-
plong = PyLong_FromLong(testcases[i].input);
573-
if (plong == NULL)
574-
return NULL;
575-
nbits = _PyLong_NumBits(plong);
576-
sign = _PyLong_Sign(plong);
577-
578-
Py_DECREF(plong);
579-
if (nbits != testcases[i].nbits)
580-
return raiseTestError("test_long_numbits",
581-
"wrong result for _PyLong_NumBits");
582-
if (sign != testcases[i].sign)
583-
return raiseTestError("test_long_numbits",
584-
"wrong result for _PyLong_Sign");
585-
}
586-
Py_RETURN_NONE;
587-
}
588-
589537
/*[clinic input]
590538
_testcapi.call_long_compact_api
591539
arg: object
@@ -631,7 +579,6 @@ static PyMethodDef test_methods[] = {
631579
_TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF
632580
_TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF
633581
_TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF
634-
_TESTCAPI_TEST_LONG_NUMBITS_METHODDEF
635582
_TESTCAPI_TEST_LONGLONG_API_METHODDEF
636583
_TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF
637584
_TESTCAPI_PYLONG_ASINT_METHODDEF

Modules/_testcapi/parts.h

+16
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,24 @@
44
// Always enable assertions
55
#undef NDEBUG
66

7+
// The _testcapi extension tests the public C API: header files in Include/ and
8+
// Include/cpython/ directories. The internal C API must not be tested by
9+
// _testcapi: use _testinternalcapi for that.
10+
//
11+
// _testcapi C files can built with the Py_BUILD_CORE_BUILTIN macro defined if
12+
// one of the Modules/Setup files asks to build _testcapi as "static"
13+
// (gh-109723).
14+
//
15+
// The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE.
16+
#undef Py_BUILD_CORE_MODULE
17+
#undef Py_BUILD_CORE_BUILTIN
18+
719
#include "Python.h"
820

21+
#ifdef Py_BUILD_CORE
22+
# error "_testcapi must test the public Python C API, not the internal C API"
23+
#endif
24+
925
int _PyTestCapi_Init_Vectorcall(PyObject *module);
1026
int _PyTestCapi_Init_Heaptype(PyObject *module);
1127
int _PyTestCapi_Init_Abstract(PyObject *module);

Modules/_testcapi/pyatomic.c

-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
* This only tests basic functionality, not any synchronizing ordering.
55
*/
66

7-
/* Always enable assertions */
8-
#undef NDEBUG
9-
10-
#include "Python.h"
117
#include "parts.h"
128

139
// We define atomic bitwise operations on these types

Modules/_testcapimodule.c

+6-19
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,13 @@
55
* standard Python regression test, via Lib/test/test_capi.py.
66
*/
77

8-
/* This module tests the public (Include/ and Include/cpython/) C API.
9-
The internal C API must not be used here: use _testinternalcapi for that.
10-
11-
The Visual Studio projects builds _testcapi with Py_BUILD_CORE_MODULE
12-
macro defined, but only the public C API must be tested here. */
13-
14-
#undef Py_BUILD_CORE_MODULE
15-
#undef Py_BUILD_CORE_BUILTIN
16-
17-
/* Always enable assertions */
18-
#undef NDEBUG
8+
// Include parts.h first since it takes care of NDEBUG and Py_BUILD_CORE macros
9+
// and including Python.h.
10+
//
11+
// Several parts of this module are broken out into files in _testcapi/.
12+
// Include definitions from there.
13+
#include "_testcapi/parts.h"
1914

20-
#include "Python.h"
2115
#include "frameobject.h" // PyFrame_New()
2216
#include "marshal.h" // PyMarshal_WriteLongToFile()
2317

@@ -29,17 +23,10 @@
2923
# include <sys/wait.h> // W_STOPCODE
3024
#endif
3125

32-
#ifdef Py_BUILD_CORE
33-
# error "_testcapi must test the public Python C API, not CPython internal C API"
34-
#endif
35-
3626
#ifdef bool
3727
# error "The public headers should not include <stdbool.h>, see gh-48924"
3828
#endif
3929

40-
// Several parts of this module are broken out into files in _testcapi/.
41-
// Include definitions from there.
42-
#include "_testcapi/parts.h"
4330
#include "_testcapi/util.h"
4431

4532

Modules/_testinternalcapi.c

+62
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "pycore_hashtable.h" // _Py_hashtable_new()
2323
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
2424
#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
25+
#include "pycore_long.h" // _PyLong_Sign()
2526
#include "pycore_object.h" // _PyObject_IsFreed()
2627
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
2728
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
@@ -1466,6 +1467,66 @@ _testinternalcapi_write_unraisable_exc_impl(PyObject *module, PyObject *exc,
14661467
}
14671468

14681469

1470+
static PyObject *
1471+
raiseTestError(const char* test_name, const char* msg)
1472+
{
1473+
PyErr_Format(PyExc_AssertionError, "%s: %s", test_name, msg);
1474+
return NULL;
1475+
}
1476+
1477+
1478+
/*[clinic input]
1479+
_testinternalcapi.test_long_numbits
1480+
[clinic start generated code]*/
1481+
1482+
static PyObject *
1483+
_testinternalcapi_test_long_numbits_impl(PyObject *module)
1484+
/*[clinic end generated code: output=745d62d120359434 input=f14ca6f638e44dad]*/
1485+
{
1486+
struct triple {
1487+
long input;
1488+
size_t nbits;
1489+
int sign;
1490+
} testcases[] = {{0, 0, 0},
1491+
{1L, 1, 1},
1492+
{-1L, 1, -1},
1493+
{2L, 2, 1},
1494+
{-2L, 2, -1},
1495+
{3L, 2, 1},
1496+
{-3L, 2, -1},
1497+
{4L, 3, 1},
1498+
{-4L, 3, -1},
1499+
{0x7fffL, 15, 1}, /* one Python int digit */
1500+
{-0x7fffL, 15, -1},
1501+
{0xffffL, 16, 1},
1502+
{-0xffffL, 16, -1},
1503+
{0xfffffffL, 28, 1},
1504+
{-0xfffffffL, 28, -1}};
1505+
size_t i;
1506+
1507+
for (i = 0; i < Py_ARRAY_LENGTH(testcases); ++i) {
1508+
size_t nbits;
1509+
int sign;
1510+
PyObject *plong;
1511+
1512+
plong = PyLong_FromLong(testcases[i].input);
1513+
if (plong == NULL)
1514+
return NULL;
1515+
nbits = _PyLong_NumBits(plong);
1516+
sign = _PyLong_Sign(plong);
1517+
1518+
Py_DECREF(plong);
1519+
if (nbits != testcases[i].nbits)
1520+
return raiseTestError("test_long_numbits",
1521+
"wrong result for _PyLong_NumBits");
1522+
if (sign != testcases[i].sign)
1523+
return raiseTestError("test_long_numbits",
1524+
"wrong result for _PyLong_Sign");
1525+
}
1526+
Py_RETURN_NONE;
1527+
}
1528+
1529+
14691530
static PyMethodDef module_functions[] = {
14701531
{"get_configs", get_configs, METH_NOARGS},
14711532
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1521,6 +1582,7 @@ static PyMethodDef module_functions[] = {
15211582
_PyCFunction_CAST(run_in_subinterp_with_config),
15221583
METH_VARARGS | METH_KEYWORDS},
15231584
_TESTINTERNALCAPI_WRITE_UNRAISABLE_EXC_METHODDEF
1585+
_TESTINTERNALCAPI_TEST_LONG_NUMBITS_METHODDEF
15241586
{NULL, NULL} /* sentinel */
15251587
};
15261588

Modules/clinic/_testinternalcapi.c.h

+18-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/c-analyzer/c_parser/preprocessor/gcc.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@
33

44
from . import common as _common
55

6-
# The following C files define the Py_LIMITED_API macro, and so must not be
7-
# built with the Py_BUILD_CORE macro defined.
8-
USE_LIMITED_C_API = frozenset((
6+
# The following C files must not built with Py_BUILD_CORE.
7+
FILES_WITHOUT_INTERNAL_CAPI = frozenset((
98
# Modules/
109
'_testcapimodule.c',
1110
'_testclinic_limited.c',
1211
'xxlimited.c',
1312
'xxlimited_35.c',
13+
))
1414

15+
# C files in the fhe following directories must not be built with
16+
# Py_BUILD_CORE.
17+
DIRS_WITHOUT_INTERNAL_CAPI = frozenset((
1518
# Modules/_testcapi/
16-
'heaptype_relative.c',
17-
'vectorcall_limited.c',
19+
'_testcapi',
1820
))
1921

2022
TOOL = 'gcc'
@@ -75,7 +77,10 @@ def preprocess(filename,
7577
filename = _normpath(filename, cwd)
7678

7779
postargs = POST_ARGS
78-
if os.path.basename(filename) not in USE_LIMITED_C_API:
80+
basename = os.path.basename(filename)
81+
dirname = os.path.basename(os.path.dirname(filename))
82+
if (basename not in FILES_WITHOUT_INTERNAL_CAPI
83+
and dirname not in DIRS_WITHOUT_INTERNAL_CAPI):
7984
postargs += ('-DPy_BUILD_CORE=1',)
8085

8186
text = _common.preprocess(

0 commit comments

Comments
 (0)