summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xLib/platform.py61
-rw-r--r--Misc/NEWS2
-rw-r--r--Python/sysmodule.c37
3 files changed, 40 insertions, 60 deletions
diff --git a/Lib/platform.py b/Lib/platform.py
index e7eaa32..3e726a7 100755
--- a/Lib/platform.py
+++ b/Lib/platform.py
@@ -498,65 +498,6 @@ _WIN32_SERVER_RELEASES = {
(6, None): "post2012ServerR2",
}
-def _get_real_winver(maj, min, build):
- if maj < 6 or (maj == 6 and min < 2):
- return maj, min, build
-
- from ctypes import (c_buffer, POINTER, byref, create_unicode_buffer,
- Structure, WinDLL)
- from ctypes.wintypes import DWORD, HANDLE
-
- class VS_FIXEDFILEINFO(Structure):
- _fields_ = [
- ("dwSignature", DWORD),
- ("dwStrucVersion", DWORD),
- ("dwFileVersionMS", DWORD),
- ("dwFileVersionLS", DWORD),
- ("dwProductVersionMS", DWORD),
- ("dwProductVersionLS", DWORD),
- ("dwFileFlagsMask", DWORD),
- ("dwFileFlags", DWORD),
- ("dwFileOS", DWORD),
- ("dwFileType", DWORD),
- ("dwFileSubtype", DWORD),
- ("dwFileDateMS", DWORD),
- ("dwFileDateLS", DWORD),
- ]
-
- kernel32 = WinDLL('kernel32')
- version = WinDLL('version')
-
- # We will immediately double the length up to MAX_PATH, but the
- # path may be longer, so we retry until the returned string is
- # shorter than our buffer.
- name_len = actual_len = 130
- while actual_len == name_len:
- name_len *= 2
- name = create_unicode_buffer(name_len)
- actual_len = kernel32.GetModuleFileNameW(HANDLE(kernel32._handle),
- name, len(name))
- if not actual_len:
- return maj, min, build
-
- size = version.GetFileVersionInfoSizeW(name, None)
- if not size:
- return maj, min, build
-
- ver_block = c_buffer(size)
- if (not version.GetFileVersionInfoW(name, None, size, ver_block) or
- not ver_block):
- return maj, min, build
-
- pvi = POINTER(VS_FIXEDFILEINFO)()
- if not version.VerQueryValueW(ver_block, "", byref(pvi), byref(DWORD())):
- return maj, min, build
-
- maj = pvi.contents.dwProductVersionMS >> 16
- min = pvi.contents.dwProductVersionMS & 0xFFFF
- build = pvi.contents.dwProductVersionLS >> 16
-
- return maj, min, build
-
def win32_ver(release='', version='', csd='', ptype=''):
try:
from sys import getwindowsversion
@@ -568,7 +509,7 @@ def win32_ver(release='', version='', csd='', ptype=''):
from _winreg import OpenKeyEx, QueryValueEx, CloseKey, HKEY_LOCAL_MACHINE
winver = getwindowsversion()
- maj, min, build = _get_real_winver(*winver[:3])
+ maj, min, build = winver._platform_version or winver[:3]
version = '{0}.{1}.{2}'.format(maj, min, build)
release = (_WIN32_CLIENT_RELEASES.get((maj, min)) or
diff --git a/Misc/NEWS b/Misc/NEWS
index 1cf1819..49879f5 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -71,6 +71,8 @@ Core and Builtins
Library
-------
+- Issue #27932: Prevent memory leak in win32_ver().
+
- Fix UnboundLocalError in socket._sendfile_use_sendfile.
- Issue #28075: Check for ERROR_ACCESS_DENIED in Windows implementation of
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 8d7e05a..f688349 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -825,6 +825,7 @@ static PyStructSequence_Field windows_version_fields[] = {
{"service_pack_minor", "Service Pack minor version number"},
{"suite_mask", "Bit mask identifying available product suites"},
{"product_type", "System product type"},
+ {"_platform_version", "Diagnostic version number"},
{0}
};
@@ -849,6 +850,12 @@ sys_getwindowsversion(PyObject *self)
PyObject *version;
int pos = 0;
OSVERSIONINFOEX ver;
+ DWORD realMajor, realMinor, realBuild;
+ HANDLE hKernel32;
+ wchar_t kernel32_path[MAX_PATH];
+ LPVOID verblock;
+ DWORD verblock_size;
+
ver.dwOSVersionInfoSize = sizeof(ver);
if (!GetVersionEx((OSVERSIONINFO*) &ver))
return PyErr_SetFromWindowsErr(0);
@@ -867,10 +874,40 @@ sys_getwindowsversion(PyObject *self)
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));
PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));
+ realMajor = ver.dwMajorVersion;
+ realMinor = ver.dwMinorVersion;
+ realBuild = ver.dwBuildNumber;
+
+ // GetVersion will lie if we are running in a compatibility mode.
+ // We need to read the version info from a system file resource
+ // to accurately identify the OS version. If we fail for any reason,
+ // just return whatever GetVersion said.
+ hKernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (hKernel32 && GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH) &&
+ (verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL)) &&
+ (verblock = PyMem_RawMalloc(verblock_size))) {
+ VS_FIXEDFILEINFO *ffi;
+ UINT ffi_len;
+
+ if (GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) &&
+ VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) {
+ realMajor = HIWORD(ffi->dwProductVersionMS);
+ realMinor = LOWORD(ffi->dwProductVersionMS);
+ realBuild = HIWORD(ffi->dwProductVersionLS);
+ }
+ PyMem_RawFree(verblock);
+ }
+ PyStructSequence_SET_ITEM(version, pos++, PyTuple_Pack(3,
+ PyLong_FromLong(realMajor),
+ PyLong_FromLong(realMinor),
+ PyLong_FromLong(realBuild)
+ ));
+
if (PyErr_Occurred()) {
Py_DECREF(version);
return NULL;
}
+
return version;
}