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