From 16c3c3c4c08e510499259e571e91ddf168d7768a Mon Sep 17 00:00:00 2001 From: SomberNight Date: Fri, 26 May 2023 15:34:18 +0000 Subject: [PATCH] appimage build: bump python version (3.9.15->3.10.11) --- contrib/build-linux/appimage/make_appimage.sh | 11 ++- ...> python-3.10-reproducible-buildinfo.diff} | 10 +- .../patches/python-3.10-reproducible-pyc.diff | 97 +++++++++++++++++++ 3 files changed, 110 insertions(+), 8 deletions(-) rename contrib/build-linux/appimage/patches/{python-3.9-reproducible-buildinfo.diff => python-3.10-reproducible-buildinfo.diff} (59%) create mode 100644 contrib/build-linux/appimage/patches/python-3.10-reproducible-pyc.diff diff --git a/contrib/build-linux/appimage/make_appimage.sh b/contrib/build-linux/appimage/make_appimage.sh index ec8c9aeb3..5acf46349 100755 --- a/contrib/build-linux/appimage/make_appimage.sh +++ b/contrib/build-linux/appimage/make_appimage.sh @@ -19,8 +19,8 @@ git -C "$PROJECT_ROOT" rev-parse 2>/dev/null || fail "Building outside a git clo export GCC_STRIP_BINARIES="1" # pinned versions -PYTHON_VERSION=3.9.15 -PY_VER_MAJOR="3.9" # as it appears in fs paths +PYTHON_VERSION=3.10.11 +PY_VER_MAJOR="3.10" # as it appears in fs paths PKG2APPIMAGE_COMMIT="a9c85b7e61a3a883f4a35c41c5decb5af88b6b5d" VERSION=$(git describe --tags --dirty --always) @@ -41,7 +41,7 @@ download_if_not_exist "$CACHEDIR/appimagetool" "https://github.com/AppImage/AppI verify_hash "$CACHEDIR/appimagetool" "df3baf5ca5facbecfc2f3fa6713c29ab9cefa8fd8c1eac5d283b79cab33e4acb" download_if_not_exist "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz" -verify_hash "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" "12daff6809528d9f6154216950423c9e30f0e47336cb57c6aa0b4387dd5eb4b2" +verify_hash "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" "3c3bc3048303721c904a03eb8326b631e921f11cc3be2988456a42f115daf04c" @@ -55,8 +55,9 @@ tar xf "$CACHEDIR/Python-$PYTHON_VERSION.tar.xz" -C "$CACHEDIR" cd "$CACHEDIR/Python-$PYTHON_VERSION" LC_ALL=C export BUILD_DATE=$(date -u -d "@$SOURCE_DATE_EPOCH" "+%b %d %Y") LC_ALL=C export BUILD_TIME=$(date -u -d "@$SOURCE_DATE_EPOCH" "+%H:%M:%S") - # Patch taken from Ubuntu http://archive.ubuntu.com/ubuntu/pool/main/p/python3.9/python3.9_3.9.5-3~21.04.debian.tar.xz - patch -p1 < "$CONTRIB_APPIMAGE/patches/python-3.9-reproducible-buildinfo.diff" + # Patches taken from Ubuntu http://archive.ubuntu.com/ubuntu/pool/main/p/python3.10/python3.10_3.10.7-1ubuntu0.3.debian.tar.xz + patch -p1 < "$CONTRIB_APPIMAGE/patches/python-3.10-reproducible-buildinfo.diff" + patch -p1 < "$CONTRIB_APPIMAGE/patches/python-3.10-reproducible-pyc.diff" ./configure \ --cache-file="$CACHEDIR/python.config.cache" \ --prefix="$APPDIR/usr" \ diff --git a/contrib/build-linux/appimage/patches/python-3.9-reproducible-buildinfo.diff b/contrib/build-linux/appimage/patches/python-3.10-reproducible-buildinfo.diff similarity index 59% rename from contrib/build-linux/appimage/patches/python-3.9-reproducible-buildinfo.diff rename to contrib/build-linux/appimage/patches/python-3.10-reproducible-buildinfo.diff index 16693a157..4f3063abd 100644 --- a/contrib/build-linux/appimage/patches/python-3.9-reproducible-buildinfo.diff +++ b/contrib/build-linux/appimage/patches/python-3.10-reproducible-buildinfo.diff @@ -1,13 +1,17 @@ -# DP: Build getbuildinfo.o with DATE/TIME values when defined +Description: Build reproduceable date and time into build info + Build information is encoded into getbuildinfo.o at build time. + Use the date and time from the debian changelog, to make this reproduceable. + +Forwarded: no --- a/Makefile.pre.in +++ b/Makefile.pre.in -@@ -795,6 +795,8 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \ +@@ -796,6 +796,8 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \ -DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \ -DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \ -DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \ + $(if $(BUILD_DATE),-DDATE='"$(BUILD_DATE)"') \ + $(if $(BUILD_TIME),-DTIME='"$(BUILD_TIME)"') \ -o $@ $(srcdir)/Modules/getbuildinfo.c - + Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile diff --git a/contrib/build-linux/appimage/patches/python-3.10-reproducible-pyc.diff b/contrib/build-linux/appimage/patches/python-3.10-reproducible-pyc.diff new file mode 100644 index 000000000..456cb33a3 --- /dev/null +++ b/contrib/build-linux/appimage/patches/python-3.10-reproducible-pyc.diff @@ -0,0 +1,97 @@ +From 36ae9beb04763d498df2114657bfbbcfe58bf913 Mon Sep 17 00:00:00 2001 +From: Brandt Bucher +Date: Mon, 23 Aug 2021 18:34:17 -0700 +Subject: [PATCH] Serialize frozenset elements deterministically + +--- + Lib/test/test_marshal.py | 25 +++++++++++++++ + .../2021-08-23-21-39-59.bpo-37596.ojRcwB.rst | 2 ++ + Python/marshal.c | 32 +++++++++++++++++++ + 3 files changed, 59 insertions(+) + create mode 100644 Misc/NEWS.d/next/Library/2021-08-23-21-39-59.bpo-37596.ojRcwB.rst + +--- a/Lib/test/test_marshal.py ++++ b/Lib/test/test_marshal.py +@@ -1,5 +1,6 @@ + from test import support + from test.support import os_helper ++from test.support.script_helper import assert_python_ok + import array + import io + import marshal +@@ -318,6 +319,31 @@ class BugsTestCase(unittest.TestCase): + for i in range(len(data)): + self.assertRaises(EOFError, marshal.loads, data[0: i]) + ++ def test_deterministic_sets(self): ++ # bpo-37596: To support reproducible builds, sets and frozensets need to ++ # have their elements serialized in a consistent order (even when they ++ # have been scrambled by hash randomization): ++ for kind in ("set", "frozenset"): ++ for elements in ( ++ "float('nan'), b'a', b'b', b'c', 'x', 'y', 'z'", ++ # Also test for bad interactions with backreferencing: ++ "('string', 1), ('string', 2), ('string', 3)", ++ ): ++ s = f"{kind}([{elements}])" ++ with self.subTest(s): ++ # First, make sure that our test case still has different ++ # orders under hash seeds 0 and 1. If this check fails, we ++ # need to update this test with different elements: ++ args = ["-c", f"print({s})"] ++ _, repr_0, _ = assert_python_ok(*args, PYTHONHASHSEED="0") ++ _, repr_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1") ++ self.assertNotEqual(repr_0, repr_1) ++ # Then, perform the actual test: ++ args = ["-c", f"import marshal; print(marshal.dumps({s}))"] ++ _, dump_0, _ = assert_python_ok(*args, PYTHONHASHSEED="0") ++ _, dump_1, _ = assert_python_ok(*args, PYTHONHASHSEED="1") ++ self.assertEqual(dump_0, dump_1) ++ + LARGE_SIZE = 2**31 + pointer_size = 8 if sys.maxsize > 0xFFFFFFFF else 4 + +--- a/Python/marshal.c ++++ b/Python/marshal.c +@@ -502,9 +502,41 @@ w_complex_object(PyObject *v, char flag, + W_TYPE(TYPE_SET, p); + n = PySet_GET_SIZE(v); + W_SIZE(n, p); ++ // bpo-37596: To support reproducible builds, sets and frozensets need ++ // to have their elements serialized in a consistent order (even when ++ // they have been scrambled by hash randomization). To ensure this, we ++ // use an order equivalent to sorted(v, key=marshal.dumps): ++ PyObject *pairs = PyList_New(0); ++ if (pairs == NULL) { ++ p->error = WFERR_NOMEMORY; ++ return; ++ } + while (_PySet_NextEntry(v, &pos, &value, &hash)) { ++ PyObject *dump = PyMarshal_WriteObjectToString(value, p->version); ++ if (dump == NULL) { ++ p->error = WFERR_UNMARSHALLABLE; ++ goto anyset_done; ++ } ++ PyObject *pair = PyTuple_Pack(2, dump, value); ++ Py_DECREF(dump); ++ if (pair == NULL || PyList_Append(pairs, pair)) { ++ p->error = WFERR_NOMEMORY; ++ Py_XDECREF(pair); ++ goto anyset_done; ++ } ++ Py_DECREF(pair); ++ } ++ if (PyList_Sort(pairs)) { ++ p->error = WFERR_NOMEMORY; ++ goto anyset_done; ++ } ++ for (Py_ssize_t i = 0; i < n; i++) { ++ PyObject *pair = PyList_GET_ITEM(pairs, i); ++ value = PyTuple_GET_ITEM(pair, 1); + w_object(value, p); + } ++ anyset_done: ++ Py_DECREF(pairs); + } + else if (PyCode_Check(v)) { + PyCodeObject *co = (PyCodeObject *)v;