mirror of https://github.com/python/cpython
Issue #27932: Prevent memory leak in win32_ver().
This commit is contained in:
parent
1c75c18ed2
commit
1ec262be80
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue