Skip to content

Commit fdcb621

Browse files
committed
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.
1 parent 4ebdf7f commit fdcb621

3 files changed

Lines changed: 22 additions & 5 deletions

File tree

Lib/test/test_winreg.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,18 @@ def test_reflection_unsupported(self):
314314
finally:
315315
DeleteKey(HKEY_CURRENT_USER, test_key_name)
316316

317+
def test_setvalueex_value_range(self):
318+
# Test for Issue #14420, accept proper ranges for SetValueEx.
319+
# Py2Reg, which gets called by SetValueEx, was using PyLong_AsLong,
320+
# thus raising OverflowError. The implementation now uses
321+
# PyLong_AsUnsignedLong to match DWORD's size.
322+
try:
323+
with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
324+
self.assertNotEqual(ck.handle, 0)
325+
SetValueEx(ck, "test_name", None, REG_DWORD, 0x80000000)
326+
finally:
327+
DeleteKey(HKEY_CURRENT_USER, test_key_name)
328+
317329

318330
@unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests")
319331
class RemoteWinregTests(BaseWinregTests):

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ What's New in Python 2.7.4
99
Core and Builtins
1010
-----------------
1111

12+
- Issue #14420: Support the full DWORD (unsigned long) range in Py2Reg
13+
when passed a REG_DWORD value. Fixes ValueError in winreg.SetValueEx when
14+
given a long.
15+
1216
- Issue #13863: Work around buggy 'fstat' implementation on Windows / NTFS that
1317
lead to incorrect timestamps (off by one hour) being stored in .pyc files on
1418
some systems.

PC/_winreg.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,8 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
753753
Py_ssize_t i,j;
754754
switch (typ) {
755755
case REG_DWORD:
756-
if (value != Py_None && !PyInt_Check(value))
756+
if (value != Py_None &&
757+
!(PyInt_Check(value) || PyLong_Check(value)))
757758
return FALSE;
758759
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
759760
if (*retDataBuf==NULL){
@@ -765,10 +766,10 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
765766
DWORD zero = 0;
766767
memcpy(*retDataBuf, &zero, sizeof(DWORD));
767768
}
768-
else
769-
memcpy(*retDataBuf,
770-
&PyInt_AS_LONG((PyIntObject *)value),
771-
sizeof(DWORD));
769+
else {
770+
DWORD d = PyLong_AsUnsignedLong(value);
771+
memcpy(*retDataBuf, &d, sizeof(DWORD));
772+
}
772773
break;
773774
case REG_SZ:
774775
case REG_EXPAND_SZ:

0 commit comments

Comments
 (0)