diff --git a/Lib/test/test_msilib.py b/Lib/test/test_msilib.py index 6d89ca4b773..4aa4753fc2a 100644 --- a/Lib/test/test_msilib.py +++ b/Lib/test/test_msilib.py @@ -1,5 +1,5 @@ """ Test suite for the code in msilib """ -import os.path +import os import unittest from test.support import TESTFN, import_module, unlink msilib = import_module('msilib') @@ -42,6 +42,29 @@ class MsiDatabaseTestCase(unittest.TestCase): ) self.addCleanup(unlink, db_path) + def test_summaryinfo_getproperty_issue1104(self): + db, db_path = init_database() + try: + sum_info = db.GetSummaryInformation(99) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"Installation Database") + + sum_info.SetProperty(msilib.PID_TITLE, "a" * 999) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"a" * 999) + + sum_info.SetProperty(msilib.PID_TITLE, "a" * 1000) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"a" * 1000) + + sum_info.SetProperty(msilib.PID_TITLE, "a" * 1001) + title = sum_info.GetProperty(msilib.PID_TITLE) + self.assertEqual(title, b"a" * 1001) + finally: + db = None + sum_info = None + os.unlink(db_path) + def test_database_open_failed(self): with self.assertRaises(msilib.MSIError) as cm: msilib.OpenDatabase('non-existent.msi', msilib.MSIDBOPEN_READONLY) @@ -92,7 +115,7 @@ class Test_make_id(unittest.TestCase): def test_invalid_any_char(self): self.assertEqual( msilib.make_id(".s\x82ort"), "_.s_ort") - self.assertEqual ( + self.assertEqual( msilib.make_id(".s\x82o?*+rt"), "_.s_o___rt") diff --git a/Misc/NEWS.d/next/Windows/2017-11-24-12-53-54.bpo-1104.1CWSZp.rst b/Misc/NEWS.d/next/Windows/2017-11-24-12-53-54.bpo-1104.1CWSZp.rst new file mode 100644 index 00000000000..a4043496bc2 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2017-11-24-12-53-54.bpo-1104.1CWSZp.rst @@ -0,0 +1,2 @@ +Correctly handle string length in ``msilib.SummaryInfo.GetProperty()`` to +prevent it from truncating the last character. diff --git a/PC/_msi.c b/PC/_msi.c index 024b2d3c9fd..99aef52e422 100644 --- a/PC/_msi.c +++ b/PC/_msi.c @@ -555,7 +555,7 @@ summary_getproperty(msiobj* si, PyObject *args) FILETIME fval; char sbuf[1000]; char *sval = sbuf; - DWORD ssize = sizeof(sval); + DWORD ssize = sizeof(sbuf); if (!PyArg_ParseTuple(args, "i:GetProperty", &field)) return NULL; @@ -563,6 +563,7 @@ summary_getproperty(msiobj* si, PyObject *args) status = MsiSummaryInfoGetProperty(si->h, field, &type, &ival, &fval, sval, &ssize); if (status == ERROR_MORE_DATA) { + ssize++; sval = malloc(ssize); if (sval == NULL) { return PyErr_NoMemory(); @@ -572,21 +573,29 @@ summary_getproperty(msiobj* si, PyObject *args) } switch(type) { - case VT_I2: case VT_I4: - return PyLong_FromLong(ival); + case VT_I2: + case VT_I4: + result = PyLong_FromLong(ival); + break; case VT_FILETIME: PyErr_SetString(PyExc_NotImplementedError, "FILETIME result"); - return NULL; + result = NULL; + break; case VT_LPSTR: result = PyBytes_FromStringAndSize(sval, ssize); - if (sval != sbuf) - free(sval); - return result; + break; case VT_EMPTY: - Py_RETURN_NONE; + Py_INCREF(Py_None); + result = Py_None; + break; + default: + PyErr_Format(PyExc_NotImplementedError, "result of type %d", type); + result = NULL; + break; } - PyErr_Format(PyExc_NotImplementedError, "result of type %d", type); - return NULL; + if (sval != sbuf) + free(sval); + return result; } static PyObject*