gh-116326: Handler errors correctly in `getwindowsversion` in `sysmodule` (#116339)

This commit is contained in:
Nikita Sobolev 2024-03-05 15:31:04 +03:00 committed by GitHub
parent cbf3d38cbe
commit c91bdf86ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 32 additions and 20 deletions

View File

@ -1643,12 +1643,13 @@ sys_getwindowsversion_impl(PyObject *module)
int pos = 0;
OSVERSIONINFOEXW ver;
version = PyObject_GetAttrString(module, "_cached_windows_version");
if (PyObject_GetOptionalAttrString(module, "_cached_windows_version", &version) < 0) {
return NULL;
};
if (version && PyObject_TypeCheck(version, &WindowsVersionType)) {
return version;
}
Py_XDECREF(version);
PyErr_Clear();
ver.dwOSVersionInfoSize = sizeof(ver);
if (!GetVersionExW((OSVERSIONINFOW*) &ver))
@ -1658,15 +1659,24 @@ sys_getwindowsversion_impl(PyObject *module)
if (version == NULL)
return NULL;
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId));
PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromWideChar(ver.szCSDVersion, -1));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));
#define SET_VERSION_INFO(CALL) \
do { \
PyObject *item = (CALL); \
if (item == NULL) { \
goto error; \
} \
PyStructSequence_SET_ITEM(version, pos++, item); \
} while(0)
SET_VERSION_INFO(PyLong_FromLong(ver.dwMajorVersion));
SET_VERSION_INFO(PyLong_FromLong(ver.dwMinorVersion));
SET_VERSION_INFO(PyLong_FromLong(ver.dwBuildNumber));
SET_VERSION_INFO(PyLong_FromLong(ver.dwPlatformId));
SET_VERSION_INFO(PyUnicode_FromWideChar(ver.szCSDVersion, -1));
SET_VERSION_INFO(PyLong_FromLong(ver.wServicePackMajor));
SET_VERSION_INFO(PyLong_FromLong(ver.wServicePackMinor));
SET_VERSION_INFO(PyLong_FromLong(ver.wSuiteMask));
SET_VERSION_INFO(PyLong_FromLong(ver.wProductType));
// GetVersion will lie if we are running in a compatibility mode.
// We need to read the version info from a system file resource
@ -1674,6 +1684,10 @@ sys_getwindowsversion_impl(PyObject *module)
// just return whatever GetVersion said.
PyObject *realVersion = _sys_getwindowsversion_from_kernel32();
if (!realVersion) {
if (!PyErr_ExceptionMatches(PyExc_WindowsError)) {
return NULL;
}
PyErr_Clear();
realVersion = Py_BuildValue("(kkk)",
ver.dwMajorVersion,
@ -1682,21 +1696,19 @@ sys_getwindowsversion_impl(PyObject *module)
);
}
if (realVersion) {
PyStructSequence_SET_ITEM(version, pos++, realVersion);
}
SET_VERSION_INFO(realVersion);
if (PyErr_Occurred()) {
Py_DECREF(version);
return NULL;
}
#undef SET_VERSION_INFO
if (PyObject_SetAttrString(module, "_cached_windows_version", version) < 0) {
Py_DECREF(version);
return NULL;
goto error;
}
return version;
error:
Py_DECREF(version);
return NULL;
}
#pragma warning(pop)