diff options
author | Steve Dower <steve.dower@microsoft.com> | 2016-09-09 19:09:07 (GMT) |
---|---|---|
committer | Steve Dower <steve.dower@microsoft.com> | 2016-09-09 19:09:07 (GMT) |
commit | 2a2becc1d10c1b4ae1d55720f5bdb54097fed1a4 (patch) | |
tree | c6b50c5f481e1aa6c75c26aa044df80f7e79f89c | |
parent | 06aed90a1fe6fa48919ff0f1f39181e886df9efc (diff) | |
parent | 6ceda631af2717c271e0b5b2b05a036463764418 (diff) | |
download | cpython-2a2becc1d10c1b4ae1d55720f5bdb54097fed1a4.zip cpython-2a2becc1d10c1b4ae1d55720f5bdb54097fed1a4.tar.gz cpython-2a2becc1d10c1b4ae1d55720f5bdb54097fed1a4.tar.bz2 |
Merge with 3.5
-rw-r--r-- | Lib/email/contentmanager.py | 9 | ||||
-rw-r--r-- | Lib/test/test_email/__init__.py | 12 | ||||
-rw-r--r-- | Lib/test/test_email/test_inversion.py | 23 | ||||
-rw-r--r-- | Misc/NEWS | 5 | ||||
-rw-r--r-- | PC/_msi.c | 20 |
5 files changed, 59 insertions, 10 deletions
diff --git a/Lib/email/contentmanager.py b/Lib/email/contentmanager.py index 099c314..b904ded 100644 --- a/Lib/email/contentmanager.py +++ b/Lib/email/contentmanager.py @@ -126,12 +126,13 @@ def _finalize_set(msg, disposition, filename, cid, params): msg.set_param(key, value) -# XXX: This is a cleaned-up version of base64mime.body_encode. It would -# be nice to drop both this and quoprimime.body_encode in favor of -# enhanced binascii routines that accepted a max_line_length parameter. +# XXX: This is a cleaned-up version of base64mime.body_encode (including a bug +# fix in the calculation of unencoded_bytes_per_line). It would be nice to +# drop both this and quoprimime.body_encode in favor of enhanced binascii +# routines that accepted a max_line_length parameter. def _encode_base64(data, max_line_length): encoded_lines = [] - unencoded_bytes_per_line = max_line_length * 3 // 4 + unencoded_bytes_per_line = max_line_length // 4 * 3 for i in range(0, len(data), unencoded_bytes_per_line): thisline = data[i:i+unencoded_bytes_per_line] encoded_lines.append(binascii.b2a_base64(thisline).decode('ascii')) diff --git a/Lib/test/test_email/__init__.py b/Lib/test/test_email/__init__.py index 1600159..888751e 100644 --- a/Lib/test/test_email/__init__.py +++ b/Lib/test/test_email/__init__.py @@ -120,6 +120,10 @@ def parameterize(cls): Note: if and only if the generated test name is a valid identifier can it be used to select the test individually from the unittest command line. + The values in the params dict can be a single value, a tuple, or a + dict. If a single value of a tuple, it is passed to the test function + as positional arguments. If a dict, it is a passed via **kw. + """ paramdicts = {} testers = collections.defaultdict(list) @@ -148,8 +152,12 @@ def parameterize(cls): if name.startswith(paramsname): testnameroot = 'test_' + name[len(paramsname):] for paramname, params in paramsdict.items(): - test = (lambda self, name=name, params=params: - getattr(self, name)(*params)) + if hasattr(params, 'keys'): + test = (lambda self, name=name, params=params: + getattr(self, name)(**params)) + else: + test = (lambda self, name=name, params=params: + getattr(self, name)(*params)) testname = testnameroot + '_' + paramname test.__name__ = testname testfuncs[testname] = test diff --git a/Lib/test/test_email/test_inversion.py b/Lib/test/test_email/test_inversion.py index f36e33d..8e8d676 100644 --- a/Lib/test/test_email/test_inversion.py +++ b/Lib/test/test_email/test_inversion.py @@ -7,6 +7,7 @@ producing RFC valid messages. import io import unittest from email import policy, message_from_bytes +from email.message import EmailMessage from email.generator import BytesGenerator from test.test_email import TestEmailBase, parameterize @@ -23,7 +24,10 @@ def dedent(bstr): @parameterize -class TestInversion(TestEmailBase, unittest.TestCase): +class TestInversion(TestEmailBase): + + policy = policy.default + message = EmailMessage def msg_as_input(self, msg): m = message_from_bytes(msg, policy=policy.SMTP) @@ -44,6 +48,23 @@ class TestInversion(TestEmailBase, unittest.TestCase): } + payload_params = { + 'plain_text': dict(payload='This is a test\n'*20), + 'base64_text': dict(payload=(('xy a'*40+'\n')*5), cte='base64'), + 'qp_text': dict(payload=(('xy a'*40+'\n')*5), cte='quoted-printable'), + } + + def payload_as_body(self, payload, **kw): + msg = self._make_message() + msg['From'] = 'foo' + msg['To'] = 'bar' + msg['Subject'] = 'payload round trip test' + msg.set_content(payload, **kw) + b = bytes(msg) + msg2 = message_from_bytes(b, policy=self.policy) + self.assertEqual(bytes(msg2), b) + self.assertEqual(msg2.get_content(), payload) + if __name__ == '__main__': unittest.main() @@ -113,6 +113,11 @@ Core and Builtins Library ------- +- Issue #24594: Validates persist parameter when opening MSI database + +- Issue #28047: Fixed calculation of line length used for the base64 CTE + in the new email policies. + - Issue #27576: Fix call order in OrderedDict.__init__(). - email.generator.DecodedGenerator now supports the policy keyword. @@ -955,6 +955,17 @@ static PyTypeObject msidb_Type = { 0, /*tp_is_gc*/ }; +#define Py_NOT_PERSIST(x, flag) \ + (x != (int)(flag) && \ + x != ((int)(flag) | MSIDBOPEN_PATCHFILE)) + +#define Py_INVALID_PERSIST(x) \ + (Py_NOT_PERSIST(x, MSIDBOPEN_READONLY) && \ + Py_NOT_PERSIST(x, MSIDBOPEN_TRANSACT) && \ + Py_NOT_PERSIST(x, MSIDBOPEN_DIRECT) && \ + Py_NOT_PERSIST(x, MSIDBOPEN_CREATE) && \ + Py_NOT_PERSIST(x, MSIDBOPEN_CREATEDIRECT)) + static PyObject* msiopendb(PyObject *obj, PyObject *args) { int status; @@ -962,11 +973,14 @@ static PyObject* msiopendb(PyObject *obj, PyObject *args) int persist; MSIHANDLE h; msiobj *result; - if (!PyArg_ParseTuple(args, "si:MSIOpenDatabase", &path, &persist)) return NULL; - - status = MsiOpenDatabase(path, (LPCSTR)persist, &h); + /* We need to validate that persist is a valid MSIDBOPEN_* value. Otherwise, + MsiOpenDatabase may treat the value as a pointer, leading to unexpected + behavior. */ + if (Py_INVALID_PERSIST(persist)) + return msierror(ERROR_INVALID_PARAMETER); + status = MsiOpenDatabase(path, (LPCSTR)persist, &h); if (status != ERROR_SUCCESS) return msierror(status); |