[pypy-svn] pypy default: Ensure that generated .pyc files don't set the executable bit.

amauryfa commits-noreply at bitbucket.org
Wed Jan 26 19:09:25 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r41365:dc06c9ece13f
Date: 2011-01-26 15:18 +0100
http://bitbucket.org/pypy/pypy/changeset/dc06c9ece13f/

Log:	Ensure that generated .pyc files don't set the executable bit.

diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -720,11 +720,14 @@
 
     if space.config.objspace.usepycfiles:
         cpathname = pathname + 'c'
-        mtime = int(os.stat(pathname)[stat.ST_MTIME])
+        src_stat = os.stat(pathname)
+        mtime = int(src_stat[stat.ST_MTIME])
+        mode = src_stat[stat.ST_MODE]
         stream = check_compiled_module(space, cpathname, mtime)
     else:
         cpathname = None
         mtime = 0
+        mode = 0
         stream = None
 
     if stream:
@@ -738,7 +741,7 @@
         code_w = parse_source_module(space, pathname, source)
 
         if space.config.objspace.usepycfiles and write_pyc:
-            write_compiled_module(space, code_w, cpathname, mtime)
+            write_compiled_module(space, code_w, cpathname, mode, mtime)
 
     exec_code_module(space, w_mod, code_w)
 
@@ -825,8 +828,18 @@
 
     return w_mod
 
+def open_exclusive(space, cpathname, mode):
+    try:
+        os.unlink(cpathname)
+    except OSError:
+        pass
 
-def write_compiled_module(space, co, cpathname, mtime):
+    flags = (os.O_EXCL|os.O_CREAT|os.O_WRONLY|os.O_TRUNC|
+             getattr(os, 'O_BINARY', 0))
+    fd = os.open(cpathname, flags, mode)
+    return streamio.fdopen_as_stream(fd, "wb")
+
+def write_compiled_module(space, co, cpathname, src_mode, src_mtime):
     """
     Write a compiled module to a file, placing the time of last
     modification of its source into the header.
@@ -847,10 +860,16 @@
     # Careful here: we must not crash nor leave behind something that looks
     # too much like a valid pyc file but really isn't one.
     #
+    mode = src_mode & ~0111
     try:
-        stream = streamio.open_file_as_stream(cpathname, "wb")
-    except StreamErrors:
-        return    # cannot create file
+        stream = open_exclusive(space, cpathname, mode)
+    except (OSError, StreamErrors):
+        try:
+            os.unlink(cpathname)
+        except OSError:
+            pass
+        return
+
     try:
         try:
             # will patch the header later; write zeroes until we are sure that
@@ -862,7 +881,7 @@
             # should be ok (XXX or should call os.fsync() to be sure?)
             stream.seek(0, 0)
             _w_long(stream, get_pyc_magic(space))
-            _w_long(stream, mtime)
+            _w_long(stream, src_mtime)
         finally:
             stream.close()
     except StreamErrors:

diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -722,6 +722,7 @@
     def test_write_compiled_module(self):
         space = self.space
         pathname = _testfilesource()
+        os.chmod(pathname, 0777)
         stream = streamio.open_file_as_stream(pathname, "r")
         try:
             w_ret = importing.parse_source_module(space,
@@ -733,10 +734,12 @@
         assert type(pycode) is pypy.interpreter.pycode.PyCode
 
         cpathname = str(udir.join('cpathname.pyc'))
+        mode = 0777
         mtime = 12345
         importing.write_compiled_module(space,
                                         pycode,
                                         cpathname,
+                                        mode,
                                         mtime)
 
         # check
@@ -746,6 +749,9 @@
         assert ret is not None
         ret.close()
 
+        # Check that the executable bit was removed
+        assert os.stat(cpathname).st_mode & 0111 == 0
+
         # read compiled module
         stream = streamio.open_file_as_stream(cpathname, "rb")
         try:

diff --git a/pypy/rlib/streamio.py b/pypy/rlib/streamio.py
--- a/pypy/rlib/streamio.py
+++ b/pypy/rlib/streamio.py
@@ -89,7 +89,7 @@
 def _setfd_binary(fd):
     pass
     
-def fdopen_as_stream(fd, mode, buffering):
+def fdopen_as_stream(fd, mode, buffering=-1):
     # XXX XXX XXX you want do check whether the modes are compatible
     # otherwise you get funny results
     os_flags, universal, reading, writing, basemode, binary = decode_mode(mode)


More information about the Pypy-commit mailing list