From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Tue, 24 Aug 2021 15:07:31 +0000 (-0700) Subject: [3.9] bpo-34990: Treat the pyc header's mtime in compileall as an unsigned int (GH... X-Git-Tag: v3.9.7~25 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9d3b6b2472f7c7ef841e652825de652bc8af85d7;p=thirdparty%2FPython%2Fcpython.git [3.9] bpo-34990: Treat the pyc header's mtime in compileall as an unsigned int (GH-19708) (cherry picked from commit bb21e28fd08f894ceff2405544a2f257d42b1354) Co-authored-by: Ammar Askar Co-authored-by: Stéphane Wirtel --- diff --git a/Lib/compileall.py b/Lib/compileall.py index 33fb76c54154..39f4bb394d88 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -219,8 +219,8 @@ def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, if not force: try: mtime = int(os.stat(fullname).st_mtime) - expect = struct.pack('<4sll', importlib.util.MAGIC_NUMBER, - 0, mtime) + expect = struct.pack('<4sLL', importlib.util.MAGIC_NUMBER, + 0, mtime & 0xFFFF_FFFF) for cfile in opt_cfiles.values(): with open(cfile, 'rb') as chandle: actual = chandle.read(12) diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 8df705666c09..a03735d3b761 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -75,9 +75,28 @@ class CompileallTestsBase: with open(self.bc_path, 'rb') as file: data = file.read(12) mtime = int(os.stat(self.source_path).st_mtime) - compare = struct.pack('<4sll', importlib.util.MAGIC_NUMBER, 0, mtime) + compare = struct.pack('<4sLL', importlib.util.MAGIC_NUMBER, 0, + mtime & 0xFFFF_FFFF) return data, compare + def test_year_2038_mtime_compilation(self): + # Test to make sure we can handle mtimes larger than what a 32-bit + # signed number can hold as part of bpo-34990 + try: + os.utime(self.source_path, (2**32 - 1, 2**32 - 1)) + except (OverflowError, OSError): + self.skipTest("filesystem doesn't support timestamps near 2**32") + self.assertTrue(compileall.compile_file(self.source_path)) + + def test_larger_than_32_bit_times(self): + # This is similar to the test above but we skip it if the OS doesn't + # support modification times larger than 32-bits. + try: + os.utime(self.source_path, (2**35, 2**35)) + except (OverflowError, OSError): + self.skipTest("filesystem doesn't support large timestamps") + self.assertTrue(compileall.compile_file(self.source_path)) + def recreation_check(self, metadata): """Check that compileall recreates bytecode when the new metadata is used.""" @@ -96,7 +115,7 @@ class CompileallTestsBase: def test_mtime(self): # Test a change in mtime leads to a new .pyc. - self.recreation_check(struct.pack('<4sll', importlib.util.MAGIC_NUMBER, + self.recreation_check(struct.pack('<4sLL', importlib.util.MAGIC_NUMBER, 0, 1)) def test_magic_number(self): diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 560286071c69..80c98b4b4661 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -34,14 +34,9 @@ raise_src = 'def do_raise(): raise TypeError\n' def make_pyc(co, mtime, size): data = marshal.dumps(co) - if type(mtime) is type(0.0): - # Mac mtimes need a bit of special casing - if mtime < 0x7fffffff: - mtime = int(mtime) - else: - mtime = int(-0x100000000 + int(mtime)) pyc = (importlib.util.MAGIC_NUMBER + - struct.pack("