Fix #14420. Check for PyLong as well as PyInt when converting in Py2Reg.

This fixes a ValueError seen in winreg.SetValueEx when passed long
winreg.REG_DWORD values that should be supported by the underlying API.
This commit is contained in:
Brian Curtin 2012-12-27 12:28:51 -06:00
parent 4a5a4c2808
commit 0e091b0365
3 changed files with 22 additions and 5 deletions

View File

@ -314,6 +314,18 @@ class LocalWinregTests(BaseWinregTests):
finally: finally:
DeleteKey(HKEY_CURRENT_USER, test_key_name) DeleteKey(HKEY_CURRENT_USER, test_key_name)
def test_setvalueex_value_range(self):
# Test for Issue #14420, accept proper ranges for SetValueEx.
# Py2Reg, which gets called by SetValueEx, was using PyLong_AsLong,
# thus raising OverflowError. The implementation now uses
# PyLong_AsUnsignedLong to match DWORD's size.
try:
with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
self.assertNotEqual(ck.handle, 0)
SetValueEx(ck, "test_name", None, REG_DWORD, 0x80000000)
finally:
DeleteKey(HKEY_CURRENT_USER, test_key_name)
@unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests") @unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests")
class RemoteWinregTests(BaseWinregTests): class RemoteWinregTests(BaseWinregTests):

View File

@ -9,6 +9,10 @@ What's New in Python 2.7.4
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #14420: Support the full DWORD (unsigned long) range in Py2Reg
when passed a REG_DWORD value. Fixes ValueError in winreg.SetValueEx when
given a long.
- Issue #13863: Work around buggy 'fstat' implementation on Windows / NTFS that - Issue #13863: Work around buggy 'fstat' implementation on Windows / NTFS that
lead to incorrect timestamps (off by one hour) being stored in .pyc files on lead to incorrect timestamps (off by one hour) being stored in .pyc files on
some systems. some systems.

View File

@ -753,7 +753,8 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
Py_ssize_t i,j; Py_ssize_t i,j;
switch (typ) { switch (typ) {
case REG_DWORD: case REG_DWORD:
if (value != Py_None && !PyInt_Check(value)) if (value != Py_None &&
!(PyInt_Check(value) || PyLong_Check(value)))
return FALSE; return FALSE;
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1); *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
if (*retDataBuf==NULL){ if (*retDataBuf==NULL){
@ -765,10 +766,10 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
DWORD zero = 0; DWORD zero = 0;
memcpy(*retDataBuf, &zero, sizeof(DWORD)); memcpy(*retDataBuf, &zero, sizeof(DWORD));
} }
else else {
memcpy(*retDataBuf, DWORD d = PyLong_AsUnsignedLong(value);
&PyInt_AS_LONG((PyIntObject *)value), memcpy(*retDataBuf, &d, sizeof(DWORD));
sizeof(DWORD)); }
break; break;
case REG_SZ: case REG_SZ:
case REG_EXPAND_SZ: case REG_EXPAND_SZ: