8000 bpo-43984: Allow winreg.SetValueEx to set -1 without treating it as a… · python/cpython@3939a4b · GitHub
[go: up one dir, main page]

Skip to content

Commit 3939a4b

Browse files
bpo-43984: Allow winreg.SetValueEx to set -1 without treating it as an error (GH-25775)
(cherry picked from commit a29a7b9) Co-authored-by: Shreyan Avigyan <shreyan.avigyan@gmail.com>
1 parent ecb16d5 commit 3939a4b

File tree

3 files changed

+64
-33
lines changed

3 files changed

+64
-33
lines changed

Lib/test/test_winreg.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ def _write_test_data(self, root_key, subkeystr="sub_key",
113113
"does not close the actual key!")
114114
except OSError:
115115
pass
116-
117116
def _read_test_data(self, root_key, subkeystr="sub_key", OpenKey=OpenKey):
118117
# Check we can get default value for this key.
119118
val = QueryValue(root_key, test_key_name)
@@ -340,6 +339,23 @@ def test_setvalueex_value_range(self):
340339
finally:
341340
DeleteKey(HKEY_CURRENT_USER, test_key_name)
342341

342+
def test_setvalueex_negative_one_check(self):
343+
# Test for Issue #43984, check -1 was not set by SetValueEx.
344+
# Py2Reg, which gets called by SetValueEx, wasn't checking return
345+
# value by PyLong_AsUnsignedLong, thus setting -1 as value in the registry.
346+
# The implementation now checks PyLong_AsUnsignedLong return value to assure
347+
# the value set was not -1.
348+
try:
349+
with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
350+
with self.assertRaises(OverflowError):
351+
SetValueEx(ck, "test_name_dword", None, REG_DWORD, -1)
352+
SetValueEx(ck, "test_name_qword", None, REG_QWORD, -1)
353+
self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_dword")
354+
self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_qword")
355+
356+
finally:
357+
DeleteKey(HKEY_CURRENT_USER, test_key_name)
358+
343359
def test_queryvalueex_return_value(self):
344360
# Test for Issue #16759, return unsigned int from QueryValueEx.
345361
# Reg2Py, which gets called by QueryValueEx, was returning a value
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:meth:`winreg.SetValueEx` now leaves the target value untouched in the case of conversion errors.
2+
Previously, ``-1`` would be written in case of such errors.
3+

PC/winreg.c

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -564,42 +564,54 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
564564
{
565565
Py_ssize_t i,j;
566566
switch (typ) {
567-
case REG_DWORD:
568-
if (value != Py_None && !PyLong_Check(value))
569-
return FALSE;
570-
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
571-
if (*retDataBuf == NULL){
572-
PyErr_NoMemory();
573-
return FALSE;
574-
}
575-
*retDataSize = sizeof(DWORD);
576-
if (value == Py_None) {
577-
DWORD zero = 0;
578-
memcpy(*retDataBuf, &zero, sizeof(DWORD));
579-
}
580-
else {
581-
DWORD d = PyLong_AsUnsignedLong(value);
567+
case REG_DWORD:
568+
{
569+
if (value != Py_None && !PyLong_Check(value)) {
570+
return FALSE;
571+
}
572+
DWORD d;
573+
if (value == Py_None) {
574+
d = 0;
575+
}
576+
else if (PyLong_Check(value)) {
577+
d = PyLong_AsUnsignedLong(value);
578+
if (d == (DWORD)(-1) && PyErr_Occurred()) {
579+
return FALSE;
580+
}
581+
}
582+
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
583+
if (*retDataBuf == NULL) {
584+
PyErr_NoMemory();
585+
return FALSE;
586+
}
582587
memcpy(*retDataBuf, &d, sizeof(DWORD));
588+
*retDataSize = sizeof(DWORD);
589+
break;
583590
}
584-
break;
585-
case REG_QWORD:
586-
if (value != Py_None && !PyLong_Check(value))
587-
return FALSE;
588-
*retDataBuf = (BYTE *)PyMem_NEW(DWORD64, 1);
589-
if (*retDataBuf == NULL){
590-
PyErr_NoMemory();
591-
return FALSE;
592-
}
593-
*retDataSize = sizeof(DWORD64);
594-
if (value == Py_None) {
595-
DWORD64 zero = 0;
596-
memcpy(*retDataBuf, &zero, sizeof(DWORD64));
597-
}
598-
else {
599-
DWORD64 d = PyLong_AsUnsignedLongLong(value);
591+
case REG_QWORD:
592+
{
593+
if (value != Py_None && !PyLong_Check(value)) {
594+
return FALSE;
595+
}
596+
DWORD64 d;
597+
if (value == Py_None) {
598+
d = 0;
599+
}
600+
else if (PyLong_Check(value)) {
601+
d = PyLong_AsUnsignedLongLong(value);
602+
if (d == (DWORD64)(-1) && PyErr_Occurred()) {
603+
return FALSE;
604+
}
605+
}
606+
*retDataBuf = (BYTE *)PyMem_NEW(DWORD64, 1);
607+
if (*retDataBuf == NULL) {
608+
PyErr_NoMemory();
609+
return FALSE;
610+
}
600611
memcpy(*retDataBuf, &d, sizeof(DWORD64));
612+
*retDataSize = sizeof(DWORD64);
613+
break;
601614
}
602-
break;
603615
case REG_SZ:
604616
case REG_EXPAND_SZ:
605617
{

0 commit comments

Comments
 (0)
0