Skip to content

Commit 8ae2ef8

Browse files
committed
pythongh-115382: Fix cross compiles when host and target use same SOABI
Previously, when a build was configured to use a host interpreter via --with-build-python, the PYTHON_FOR_BUILD config value included a path in PYTHONPATH that pointed to the target's built external modules. For "normal" foreign architecture cross compiles, when loading compiled external libraries, the target libraries were processed first due to their precedence in sys.path. These libraries were then ruled out due to a mismatch in the SOABI so the import mechanism continued searching until it found the host's native modules. However, if the host interpreter and the target python were on the same version + SOABI combination, the host interpreter would attempt to load the target's external modules due to their precedence in sys.path. Despite the "match", the target build may have been linked against a different libc or may include unsupported instructions so loading or executing the target's external modules can lead to crashes. Now, the path to the target's external modules is no longer defined in PYTHONPATH to prevent accidentally loading these foreign modules. One caveat is that during certain build stages, the target's sysconfig module requires higher precedence than the host's version in order to accurately query the target build's configuration. This worked previously due to the target's sysconfig data module having precedence over the host's (see above). In order to keep this desired behavior, a new environment variable, _PYTHON_SYSCONFIGDATA_PATH, has been defined so sysconfig can search this directory for the target's sysconfig data. Signed-off-by: Vincent Fazio <vfazio@gmail.com>
1 parent 3383d6a commit 8ae2ef8

File tree

5 files changed

+16
-3
lines changed

5 files changed

+16
-3
lines changed

Diff for: Lib/sysconfig/__init__.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,18 @@ def _init_posix(vars):
337337
"""Initialize the module as appropriate for POSIX systems."""
338338
# _sysconfigdata is generated at build time, see _generate_posix_vars()
339339
name = _get_sysconfigdata_name()
340-
_temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
340+
341+
# For cross builds, this value will be specified so sysconfigdata for the
342+
# target can be imported. It cannot be in PYTHONPATH, as foreign modules in
343+
# sys.path can cause crashes when loaded by the host interpreter.
344+
if (path := os.environ.get('_PYTHON_SYSCONFIGDATA_PATH')) is not None:
345+
from importlib.machinery import FileFinder, SourceFileLoader, SOURCE_SUFFIXES
346+
from importlib.util import module_from_spec
347+
spec = FileFinder(path, (SourceFileLoader, SOURCE_SUFFIXES)).find_spec(name)
348+
_temp = module_from_spec(spec)
349+
spec.loader.exec_module(_temp)
350+
else:
351+
_temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
341352
build_time_vars = _temp.build_time_vars
342353
vars.update(build_time_vars)
343354

Diff for: Lib/test/libregrtest/main.py

+1
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ def _add_cross_compile_opts(self, regrtest_opts):
584584
'_PYTHON_PROJECT_BASE',
585585
'_PYTHON_HOST_PLATFORM',
586586
'_PYTHON_SYSCONFIGDATA_NAME',
587+
"_PYTHON_SYSCONFIGDATA_PATH",
587588
'PYTHONPATH'
588589
}
589590
old_environ = os.environ

Diff for: Lib/test/pythoninfo.py

+1
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ def format_groups(groups):
326326
"_PYTHON_HOST_PLATFORM",
327327
"_PYTHON_PROJECT_BASE",
328328
"_PYTHON_SYSCONFIGDATA_NAME",
329+
"_PYTHON_SYSCONFIGDATA_PATH",
329330
"__PYVENV_LAUNCHER__",
330331

331332
# Sanitizer options

Diff for: configure

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

Diff for: configure.ac

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ AC_ARG_WITH([build-python],
164164
dnl Build Python interpreter is used for regeneration and freezing.
165165
ac_cv_prog_PYTHON_FOR_REGEN=$with_build_python
166166
PYTHON_FOR_FREEZE="$with_build_python"
167-
PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$with_build_python
167+
PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) _PYTHON_SYSCONFIGDATA_PATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`) '$with_build_python
168168
AC_MSG_RESULT([$with_build_python])
169169
], [
170170
AS_VAR_IF([cross_compiling], [yes],

0 commit comments

Comments
 (0)