Add patch to work around magic number bump in Python 3.5.3 source code

Issue: http://bugs.python.org/issue27286
This commit is contained in:
Iryna Shcherbina 2017-02-10 11:40:30 +01:00
parent 7709829ab9
commit 8ed4c75417
2 changed files with 171 additions and 1 deletions

View File

@ -0,0 +1,160 @@
commit d4c9b1346e7c99a3b646aae5249fa276f2eef3fe
Author: Petr Viktorin <encukou@gmail.com>
Date: Thu Feb 9 16:48:14 2017 +0100
Workaround for issue27286 fallout - magic number bumped in minor release
CPython 3.5.3 has bumped the pyc-file magic number due to a bug in how
BUILD_MAP_UNPACK_WITH_CALL was compiled, causing undefined behavior
when calling a function with generalized kwarg unpacking (PEP 448)
conflicting keyword names.
Fedora packages are built with the old magic number, and we can't just
rebuild all Python packages in a released system. Trying to load the
system .pyc files using Python 3.5.3+ as an unprivileged user results
in Python trying to update the .pyc's. Normally it fails when that's
not possible, but the attempts are driving SELinux crazy.
To work around that, accept the old magic number when loading .pyc's.
Fedora packages with .pyc files that contain the BUILD_MAP_UNPACK_WITH_CALL
opcode will be rebuilt.
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index e54d691..c3ecd74 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -242,6 +242,11 @@ _code_type = type(_write_atomic.__code__)
MAGIC_NUMBER = (3351).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
+# workaround for issue27286 fallout
+if _RAW_MAGIC_NUMBER != 168627479:
+ raise SystemError('Magic number mismatch (misapplied issue27286 workaround?)')
+_BACKCOMPAT_MAGIC_NUMBER = (3350).to_bytes(2, 'little') + b'\r\n'
+
_PYCACHE = '__pycache__'
_OPT = 'opt-'
diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py
index e1fa07a..a15cf00 100644
--- a/Lib/importlib/util.py
+++ b/Lib/importlib/util.py
@@ -4,7 +4,7 @@ from ._bootstrap import module_from_spec
from ._bootstrap import _resolve_name
from ._bootstrap import spec_from_loader
from ._bootstrap import _find_spec
-from ._bootstrap_external import MAGIC_NUMBER
+from ._bootstrap_external import MAGIC_NUMBER, _BACKCOMPAT_MAGIC_NUMBER
from ._bootstrap_external import cache_from_source
from ._bootstrap_external import decode_source
from ._bootstrap_external import source_from_cache
diff --git a/Lib/pkgutil.py b/Lib/pkgutil.py
index 81d418d..318d982 100644
--- a/Lib/pkgutil.py
+++ b/Lib/pkgutil.py
@@ -37,7 +37,9 @@ def read_code(stream):
import marshal
magic = stream.read(4)
- if magic != importlib.util.MAGIC_NUMBER:
+ if (magic != importlib.util.MAGIC_NUMBER
+ # workaround for issue27286 fallout
+ and magic != importlib.util._BACKCOMPAT_MAGIC_NUMBER):
return None
stream.read(8) # Skip timestamp and size
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 0d0d0ab..e06901f 100755
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -289,7 +289,10 @@ def importfile(path):
"""Import a Python source file or compiled file given its path."""
magic = importlib.util.MAGIC_NUMBER
with open(path, 'rb') as file:
- is_bytecode = magic == file.read(len(magic))
+ first_bytes = file.read(len(magic))
+ is_bytecode = first_bytes in (magic,
+ # workaround for issue27286 fallout
+ importlib.util._BACKCOMPAT_MAGIC_NUMBER)
filename = os.path.basename(path)
name, ext = os.path.splitext(filename)
if is_bytecode:
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index 7473a8f..51225b6 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -1274,6 +1274,7 @@ unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime)
PyObject *code;
unsigned char *buf = (unsigned char *)PyBytes_AsString(data);
Py_ssize_t size = PyBytes_Size(data);
+ uint magic;
if (size < 12) {
PyErr_SetString(ZipImportError,
@@ -1281,7 +1282,10 @@ unmarshal_code(PyObject *pathname, PyObject *data, time_t mtime)
return NULL;
}
- if (get_uint32(buf) != (unsigned int)PyImport_GetMagicNumber()) {
+ magic = get_uint32(buf);
+ if (magic != (unsigned int)PyImport_GetMagicNumber()
+ // workaround for issue27286 fallout
+ && magic != 168627478) {
if (Py_VerboseFlag) {
PySys_FormatStderr("# %R has bad magic\n",
pathname);
diff --git a/Python/import.c b/Python/import.c
index 3579273..cec0fd1 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -502,6 +502,12 @@ PyImport_GetMagicNumber(void)
return -1;
res = PyLong_AsLong(pyc_magic);
Py_DECREF(pyc_magic);
+ if (res != 168627479) {
+ // workaround for issue27286 fallout
+ PyErr_SetString(PyExc_SystemError,
+ "Magic number mismatch (misapplied issue27286 workaround?)");
+ return -1;
+ }
return res;
}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 90cb2de..d1c38a2 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -262,6 +262,12 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *f
/* Check whether a file maybe a pyc file: Look at the extension,
the file type, and, if we may close it, at the first few bytes. */
+static int
+_check_half_magic(read_value, magic) {
+ // workaround for issue27286 fallout
+ return (read_value == magic || read_value == 3350);
+}
+
static int
maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit)
{
@@ -290,7 +296,7 @@ maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit)
int ispyc = 0;
if (ftell(fp) == 0) {
if (fread(buf, 1, 2, fp) == 2 &&
- ((unsigned int)buf[1]<<8 | buf[0]) == halfmagic)
+ _check_half_magic(((unsigned int)buf[1]<<8 | buf[0]), halfmagic))
ispyc = 1;
rewind(fp);
}
@@ -988,7 +994,9 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals,
long PyImport_GetMagicNumber(void);
magic = PyMarshal_ReadLongFromFile(fp);
- if (magic != PyImport_GetMagicNumber()) {
+ if (magic != PyImport_GetMagicNumber()
+ // workaround for issue27286 fallout
+ && magic != 168627478) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_RuntimeError,
"Bad magic number in .pyc file");

View File

@ -112,7 +112,7 @@
Summary: Version 3 of the Python programming language aka Python 3000
Name: python3
Version: %{pybasever}.3
Release: 1%{?dist}
Release: 2%{?dist}
License: Python
Group: Development/Languages
@ -389,6 +389,10 @@ Patch206: 00206-remove-hf-from-arm-triplet.patch
# Fedora needs the default mips64-linux-gnu
Patch243: 00243-fix-mips64-triplet.patch
# 00259 #
# Caused by this issue: http://bugs.python.org/issue27286
Patch259: 00259-magic-number-bump-workaround.patch
# (New patches go here ^^^)
#
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
@ -630,6 +634,9 @@ sed -r -i s/'_PIP_VERSION = "[0-9.]+"'/'_PIP_VERSION = "%{pip_version}"'/ Lib/en
%patch206 -p1
%patch243 -p1
%patch259 -p1
rm Python/importlib_external.h # needs to be regenerated for patch259
# Currently (2010-01-15), http://docs.python.org/library is for 2.6, and there
# are many differences between 2.6 and the Python 3 library.
#
@ -1528,6 +1535,9 @@ rm -fr %{buildroot}
# ======================================================
%changelog
* Thu Feb 09 2017 Petr Viktorin <pviktori@redhat.com> - 3.5.3-2
- Add patch 259 to work around magic number bump in Python 3.5.3
* Tue Jan 31 2017 Iryna Shcherbina <ishcherb@redhat.com> - 3.5.3-1
- Rebased to version 3.5.3