compileall used the ctime of bytecode and source to determine if the bytecode

should be recreated. This created a timing hole. Fixed by just doing what
import does; check the mtime and magic number.
This commit is contained in:
Brett Cannon 2009-02-10 02:07:38 +00:00
parent 322daea7c3
commit 28d108893c
4 changed files with 84 additions and 8 deletions

View file

@ -11,10 +11,11 @@ packages -- for now, you'll have to deal with packages separately.)
See module py_compile for details of the actual byte-compilation.
"""
import os
import sys
import py_compile
import struct
import imp
__all__ = ["compile_dir","compile_path"]
@ -54,11 +55,17 @@ def compile_dir(dir, maxlevels=10, ddir=None,
if os.path.isfile(fullname):
head, tail = name[:-3], name[-3:]
if tail == '.py':
cfile = fullname + (__debug__ and 'c' or 'o')
ftime = os.stat(fullname).st_mtime
try: ctime = os.stat(cfile).st_mtime
except os.error: ctime = 0
if (ctime > ftime) and not force: continue
if not force:
try:
mtime = os.stat(fullname).st_mtime
expect = struct.pack('<4sl', imp.get_magic(), mtime)
cfile = fullname + (__debug__ and 'c' or 'o')
with open(cfile, 'rb') as chandle:
actual = chandle.read(8)
if expect == actual:
continue
except IOError:
pass
if not quiet:
print 'Compiling', fullname, '...'
try:
@ -80,7 +87,8 @@ def compile_dir(dir, maxlevels=10, ddir=None,
name != os.curdir and name != os.pardir and \
os.path.isdir(fullname) and \
not os.path.islink(fullname):
if not compile_dir(fullname, maxlevels - 1, dfile, force, rx, quiet):
if not compile_dir(fullname, maxlevels - 1, dfile, force, rx,
quiet):
success = 0
return success