summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xLib/mailbox.py5
-rw-r--r--Lib/multiprocessing/connection.py8
-rw-r--r--Lib/shutil.py14
-rw-r--r--Lib/subprocess.py12
-rw-r--r--Lib/test/test_dict.py11
-rw-r--r--Lib/test/test_long.py3
-rw-r--r--Lib/test/test_mailbox.py51
-rw-r--r--Modules/bz2module.c1
-rw-r--r--Modules/fcntlmodule.c5
-rw-r--r--Objects/dictobject.c4
-rw-r--r--Objects/longobject.c6
-rw-r--r--Python/pystate.c4
-rw-r--r--Python/thread.c12
13 files changed, 115 insertions, 21 deletions
diff --git a/Lib/mailbox.py b/Lib/mailbox.py
index 38ff0b1..ab915ed 100755
--- a/Lib/mailbox.py
+++ b/Lib/mailbox.py
@@ -394,7 +394,8 @@ class Maildir(Mailbox):
result = Maildir(path, factory=self._factory)
maildirfolder_path = os.path.join(path, 'maildirfolder')
if not os.path.exists(maildirfolder_path):
- os.close(os.open(maildirfolder_path, os.O_CREAT | os.O_WRONLY))
+ os.close(os.open(maildirfolder_path, os.O_CREAT | os.O_WRONLY,
+ 0o666))
return result
def remove_folder(self, folder):
@@ -1900,7 +1901,7 @@ def _unlock_file(f):
def _create_carefully(path):
"""Create a file if it doesn't exist and open for reading and writing."""
- fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR)
+ fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0o666)
try:
return open(path, 'r+', newline='')
finally:
diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py
index b6f5bde..b962060 100644
--- a/Lib/multiprocessing/connection.py
+++ b/Lib/multiprocessing/connection.py
@@ -11,6 +11,7 @@ __all__ = [ 'Client', 'Listener', 'Pipe' ]
import os
import sys
import socket
+import errno
import time
import tempfile
import itertools
@@ -215,10 +216,7 @@ class SocketListener(object):
self._socket = socket.socket(getattr(socket, family))
self._socket.bind(address)
self._socket.listen(backlog)
- address = self._socket.getsockname()
- if type(address) is tuple:
- address = (socket.getfqdn(address[0]),) + address[1:]
- self._address = address
+ self._address = self._socket.getsockname()
self._family = family
self._last_accepted = None
@@ -253,7 +251,7 @@ def SocketClient(address):
try:
s.connect(address)
except socket.error as e:
- if e.args[0] != 10061: # 10061 => connection refused
+ if e.args[0] != errno.ECONNREFUSED: # connection refused
debug('failed to connect to address %s', address)
raise
time.sleep(0.01)
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 56ea7ec..9a5f78a 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -16,6 +16,11 @@ __all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
class Error(EnvironmentError):
pass
+try:
+ WindowsError
+except NameError:
+ WindowsError = None
+
def copyfileobj(fsrc, fdst, length=16*1024):
"""copy data from file-like object fsrc to file-like object fdst"""
while 1:
@@ -162,11 +167,12 @@ def copytree(src, dst, symlinks=False, ignore=None):
errors.extend(err.args[0])
try:
copystat(src, dst)
- except WindowsError:
- # can't copy file access times on Windows
- pass
except OSError as why:
- errors.extend((src, dst, str(why)))
+ if WindowsError is not None and isinstance(why, WindowsError):
+ # Copying file access times may fail on Windows
+ pass
+ else:
+ errors.extend((src, dst, str(why)))
if errors:
raise Error(errors)
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index e94fc2c..d3e9692 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -375,7 +375,7 @@ _active = []
def _cleanup():
for inst in _active[:]:
- res = inst.poll(_deadstate=sys.maxsize)
+ res = inst._internal_poll(_deadstate=sys.maxsize)
if res is not None and res >= 0:
try:
_active.remove(inst)
@@ -635,7 +635,7 @@ class Popen(object):
# We didn't get to successfully create a child process.
return
# In case the child hasn't been waited on, check if it's done.
- self.poll(_deadstate=sys.maxsize)
+ self._internal_poll(_deadstate=sys.maxsize)
if self.returncode is None and _active is not None:
# Child is still running, keep us alive until we can wait on it.
_active.append(self)
@@ -671,6 +671,10 @@ class Popen(object):
return self._communicate(input)
+ def poll(self):
+ return self._internal_poll()
+
+
if mswindows:
#
# Windows methods
@@ -842,7 +846,7 @@ class Popen(object):
errwrite.Close()
- def poll(self, _deadstate=None):
+ def _internal_poll(self, _deadstate=None):
"""Check if child process has terminated. Returns returncode
attribute."""
if self.returncode is None:
@@ -1103,7 +1107,7 @@ class Popen(object):
raise RuntimeError("Unknown child exit status!")
- def poll(self, _deadstate=None):
+ def _internal_poll(self, _deadstate=None):
"""Check if child process has terminated. Returns returncode
attribute."""
if self.returncode is None:
diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
index b518a0b..403d5eb 100644
--- a/Lib/test/test_dict.py
+++ b/Lib/test/test_dict.py
@@ -638,6 +638,17 @@ class DictTest(unittest.TestCase):
resizing = True
d[9] = 6
+ def test_empty_presized_dict_in_freelist(self):
+ # Bug #3537: if an empty but presized dict with a size larger
+ # than 7 was in the freelist, it triggered an assertion failure
+ try:
+ d = {'a': 1/0, 'b': None, 'c': None, 'd': None, 'e': None,
+ 'f': None, 'g': None, 'h': None}
+ except ZeroDivisionError:
+ pass
+ d = {}
+
+
from test import mapping_tests
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index c475878..dc04bad 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -768,7 +768,8 @@ class LongTest(unittest.TestCase):
def test_nan_inf(self):
self.assertRaises(OverflowError, int, float('inf'))
- self.assertRaises(OverflowError, int, float('nan'))
+ self.assertRaises(OverflowError, int, float('-inf'))
+ self.assertRaises(ValueError, int, float('nan'))
def test_true_division(self):
huge = 1 << 40000
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 783323f..1828381 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -709,6 +709,38 @@ class TestMaildir(TestMailbox):
for msg in self._box:
pass
+ def test_file_permissions(self):
+ # Verify that message files are created without execute permissions
+ if not hasattr(os, "stat") or not hasattr(os, "umask"):
+ return
+ msg = mailbox.MaildirMessage(self._template % 0)
+ orig_umask = os.umask(0)
+ try:
+ key = self._box.add(msg)
+ finally:
+ os.umask(orig_umask)
+ path = os.path.join(self._path, self._box._lookup(key))
+ mode = os.stat(path).st_mode
+ self.assert_(mode & 0o111 == 0)
+
+ def test_folder_file_perms(self):
+ # From bug #3228, we want to verify that the file created inside a Maildir
+ # subfolder isn't marked as executable.
+ if not hasattr(os, "stat") or not hasattr(os, "umask"):
+ return
+
+ orig_umask = os.umask(0)
+ try:
+ subfolder = self._box.add_folder('subfolder')
+ finally:
+ os.umask(orig_umask)
+
+ path = os.path.join(subfolder._path, 'maildirfolder')
+ st = os.stat(path)
+ perms = st.st_mode
+ self.assertFalse((perms & 0o111)) # Execute bits should all be off.
+
+
class _TestMboxMMDF(TestMailbox):
def tearDown(self):
@@ -800,11 +832,28 @@ class _TestMboxMMDF(TestMailbox):
self._box.close()
-
class TestMbox(_TestMboxMMDF):
_factory = lambda self, path, factory=None: mailbox.mbox(path, factory)
+ def test_file_perms(self):
+ # From bug #3228, we want to verify that the mailbox file isn't executable,
+ # even if the umask is set to something that would leave executable bits set.
+ # We only run this test on platforms that support umask.
+ if hasattr(os, 'umask') and hasattr(os, 'stat'):
+ try:
+ old_umask = os.umask(0o077)
+ self._box.close()
+ os.unlink(self._path)
+ self._box = mailbox.mbox(self._path, create=True)
+ self._box.add('')
+ self._box.close()
+ finally:
+ os.umask(old_umask)
+
+ st = os.stat(self._path)
+ perms = st.st_mode
+ self.assertFalse((perms & 0o111)) # Execute bits should all be off.
class TestMMDF(_TestMboxMMDF):
diff --git a/Modules/bz2module.c b/Modules/bz2module.c
index 562198b..c681991 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -317,6 +317,7 @@ Util_ReadAhead(BZ2FileObject *f, int bufsize)
return 0;
}
if ((f->f_buf = PyMem_Malloc(bufsize)) == NULL) {
+ PyErr_NoMemory();
return -1;
}
Py_BEGIN_ALLOW_THREADS
diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c
index 353889c..46bf4d1 100644
--- a/Modules/fcntlmodule.c
+++ b/Modules/fcntlmodule.c
@@ -530,6 +530,11 @@ all_ins(PyObject* d)
if (ins(d, "F_SHLCK", (long)F_SHLCK)) return -1;
#endif
+/* OS X (and maybe others) let you tell the storage device to flush to physical media */
+#ifdef F_FULLFSYNC
+ if (ins(d, "F_FULLFSYNC", (long)F_FULLFSYNC)) return -1;
+#endif
+
/* For F_{GET|SET}FL */
#ifdef FD_CLOEXEC
if (ins(d, "FD_CLOEXEC", (long)FD_CLOEXEC)) return -1;
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 828803c..6f3ba1b 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -242,6 +242,10 @@ PyDict_New(void)
_Py_NewReference((PyObject *)mp);
if (mp->ma_fill) {
EMPTY_TO_MINSIZE(mp);
+ } else {
+ /* At least set ma_table and ma_mask; these are wrong
+ if an empty but presized dict is added to freelist */
+ INIT_NONZERO_DICT_SLOTS(mp);
}
assert (mp->ma_used == 0);
assert (mp->ma_table == mp->ma_smalltable);
diff --git a/Objects/longobject.c b/Objects/longobject.c
index ae62cfd..3aa518b 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -271,12 +271,12 @@ PyLong_FromDouble(double dval)
neg = 0;
if (Py_IS_INFINITY(dval)) {
PyErr_SetString(PyExc_OverflowError,
- "cannot convert float infinity to int");
+ "cannot convert float infinity to integer");
return NULL;
}
if (Py_IS_NAN(dval)) {
- PyErr_SetString(PyExc_OverflowError,
- "cannot convert float NaN to int");
+ PyErr_SetString(PyExc_ValueError,
+ "cannot convert float NaN to integer");
return NULL;
}
if (dval < 0.0) {
diff --git a/Python/pystate.c b/Python/pystate.c
index c841eb3..9479256 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -291,6 +291,10 @@ tstate_delete_common(PyThreadState *tstate)
"PyThreadState_Delete: invalid tstate");
if (*p == tstate)
break;
+ /* Sanity check. These states should never happen but if
+ * they do we must abort. Otherwise we'll end up spinning in
+ * in a tight loop with the lock held. A similar check is done
+ * in thread.c find_key(). */
if (*p == prev_p)
Py_FatalError(
"PyThreadState_Delete: small circular list(!)"
diff --git a/Python/thread.c b/Python/thread.c
index 41fa1e6..d8cadba 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -260,15 +260,25 @@ static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
static struct key *
find_key(int key, void *value)
{
- struct key *p;
+ struct key *p, *prev_p;
long id = PyThread_get_thread_ident();
if (!keymutex)
return NULL;
PyThread_acquire_lock(keymutex, 1);
+ prev_p = NULL;
for (p = keyhead; p != NULL; p = p->next) {
if (p->id == id && p->key == key)
goto Done;
+ /* Sanity check. These states should never happen but if
+ * they do we must abort. Otherwise we'll end up spinning in
+ * in a tight loop with the lock held. A similar check is done
+ * in pystate.c tstate_delete_common(). */
+ if (p == prev_p)
+ Py_FatalError("tls find_key: small circular list(!)");
+ prev_p = p;
+ if (p->next == keyhead)
+ Py_FatalError("tls find_key: circular list(!)");
}
if (value == NULL) {
assert(p == NULL);