Skip to content

Commit 6a44fb2

Browse files
sobolevnmiss-islington
authored andcommitted
pythongh-116326: Handler errors correctly in getwindowsversion in sysmodule (pythonGH-116339)
(cherry picked from commit c91bdf8) Co-authored-by: Nikita Sobolev <[email protected]>
1 parent 6264c4f commit 6a44fb2

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

Python/sysmodule.c

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,12 +1584,13 @@ sys_getwindowsversion_impl(PyObject *module)
15841584
int pos = 0;
15851585
OSVERSIONINFOEXW ver;
15861586

1587-
version = PyObject_GetAttrString(module, "_cached_windows_version");
1587+
if (PyObject_GetOptionalAttrString(module, "_cached_windows_version", &version) < 0) {
1588+
return NULL;
1589+
};
15881590
if (version && PyObject_TypeCheck(version, &WindowsVersionType)) {
15891591
return version;
15901592
}
15911593
Py_XDECREF(version);
1592-
PyErr_Clear();
15931594

15941595
ver.dwOSVersionInfoSize = sizeof(ver);
15951596
if (!GetVersionExW((OSVERSIONINFOW*) &ver))
@@ -1599,22 +1600,35 @@ sys_getwindowsversion_impl(PyObject *module)
15991600
if (version == NULL)
16001601
return NULL;
16011602

1602-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion));
1603-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion));
1604-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber));
1605-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId));
1606-
PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromWideChar(ver.szCSDVersion, -1));
1607-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor));
1608-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor));
1609-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));
1610-
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));
1603+
#define SET_VERSION_INFO(CALL) \
1604+
do { \
1605+
PyObject *item = (CALL); \
1606+
if (item == NULL) { \
1607+
goto error; \
1608+
} \
1609+
PyStructSequence_SET_ITEM(version, pos++, item); \
1610+
} while(0)
1611+
1612+
SET_VERSION_INFO(PyLong_FromLong(ver.dwMajorVersion));
1613+
SET_VERSION_INFO(PyLong_FromLong(ver.dwMinorVersion));
1614+
SET_VERSION_INFO(PyLong_FromLong(ver.dwBuildNumber));
1615+
SET_VERSION_INFO(PyLong_FromLong(ver.dwPlatformId));
1616+
SET_VERSION_INFO(PyUnicode_FromWideChar(ver.szCSDVersion, -1));
1617+
SET_VERSION_INFO(PyLong_FromLong(ver.wServicePackMajor));
1618+
SET_VERSION_INFO(PyLong_FromLong(ver.wServicePackMinor));
1619+
SET_VERSION_INFO(PyLong_FromLong(ver.wSuiteMask));
1620+
SET_VERSION_INFO(PyLong_FromLong(ver.wProductType));
16111621

16121622
// GetVersion will lie if we are running in a compatibility mode.
16131623
// We need to read the version info from a system file resource
16141624
// to accurately identify the OS version. If we fail for any reason,
16151625
// just return whatever GetVersion said.
16161626
PyObject *realVersion = _sys_getwindowsversion_from_kernel32();
16171627
if (!realVersion) {
1628+
if (!PyErr_ExceptionMatches(PyExc_WindowsError)) {
1629+
return NULL;
1630+
}
1631+
16181632
PyErr_Clear();
16191633
realVersion = Py_BuildValue("(kkk)",
16201634
ver.dwMajorVersion,
@@ -1623,21 +1637,19 @@ sys_getwindowsversion_impl(PyObject *module)
16231637
);
16241638
}
16251639

1626-
if (realVersion) {
1627-
PyStructSequence_SET_ITEM(version, pos++, realVersion);
1628-
}
1640+
SET_VERSION_INFO(realVersion);
16291641

1630-
if (PyErr_Occurred()) {
1631-
Py_DECREF(version);
1632-
return NULL;
1633-
}
1642+
#undef SET_VERSION_INFO
16341643

16351644
if (PyObject_SetAttrString(module, "_cached_windows_version", version) < 0) {
1636-
Py_DECREF(version);
1637-
return NULL;
1645+
goto error;
16381646
}
16391647

16401648
return version;
1649+
1650+
error:
1651+
Py_DECREF(version);
1652+
return NULL;
16411653
}
16421654

16431655
#pragma warning(pop)

0 commit comments

Comments
 (0)