mirror of
https://github.com/python/cpython.git
synced 2025-08-31 22:18:28 +00:00
bpo-43984: Allow winreg.SetValueEx to set -1 without treating it as an error (GH-25775)
(cherry picked from commit a29a7b9b78
)
Co-authored-by: Shreyan Avigyan <shreyan.avigyan@gmail.com>
This commit is contained in:
parent
ecb16d5d63
commit
3939a4b7d9
3 changed files with 64 additions and 33 deletions
|
@ -113,7 +113,6 @@ class BaseWinregTests(unittest.TestCase):
|
||||||
"does not close the actual key!")
|
"does not close the actual key!")
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _read_test_data(self, root_key, subkeystr="sub_key", OpenKey=OpenKey):
|
def _read_test_data(self, root_key, subkeystr="sub_key", OpenKey=OpenKey):
|
||||||
# Check we can get default value for this key.
|
# Check we can get default value for this key.
|
||||||
val = QueryValue(root_key, test_key_name)
|
val = QueryValue(root_key, test_key_name)
|
||||||
|
@ -340,6 +339,23 @@ class LocalWinregTests(BaseWinregTests):
|
||||||
finally:
|
finally:
|
||||||
DeleteKey(HKEY_CURRENT_USER, test_key_name)
|
DeleteKey(HKEY_CURRENT_USER, test_key_name)
|
||||||
|
|
||||||
|
def test_setvalueex_negative_one_check(self):
|
||||||
|
# Test for Issue #43984, check -1 was not set by SetValueEx.
|
||||||
|
# Py2Reg, which gets called by SetValueEx, wasn't checking return
|
||||||
|
# value by PyLong_AsUnsignedLong, thus setting -1 as value in the registry.
|
||||||
|
# The implementation now checks PyLong_AsUnsignedLong return value to assure
|
||||||
|
# the value set was not -1.
|
||||||
|
try:
|
||||||
|
with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
|
||||||
|
with self.assertRaises(OverflowError):
|
||||||
|
SetValueEx(ck, "test_name_dword", None, REG_DWORD, -1)
|
||||||
|
SetValueEx(ck, "test_name_qword", None, REG_QWORD, -1)
|
||||||
|
self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_dword")
|
||||||
|
self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_qword")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
DeleteKey(HKEY_CURRENT_USER, test_key_name)
|
||||||
|
|
||||||
def test_queryvalueex_return_value(self):
|
def test_queryvalueex_return_value(self):
|
||||||
# Test for Issue #16759, return unsigned int from QueryValueEx.
|
# Test for Issue #16759, return unsigned int from QueryValueEx.
|
||||||
# Reg2Py, which gets called by QueryValueEx, was returning a value
|
# Reg2Py, which gets called by QueryValueEx, was returning a value
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
:meth:`winreg.SetValueEx` now leaves the target value untouched in the case of conversion errors.
|
||||||
|
Previously, ``-1`` would be written in case of such errors.
|
||||||
|
|
76
PC/winreg.c
76
PC/winreg.c
|
@ -564,42 +564,54 @@ 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 && !PyLong_Check(value))
|
{
|
||||||
return FALSE;
|
if (value != Py_None && !PyLong_Check(value)) {
|
||||||
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
|
return FALSE;
|
||||||
if (*retDataBuf == NULL){
|
}
|
||||||
PyErr_NoMemory();
|
DWORD d;
|
||||||
return FALSE;
|
if (value == Py_None) {
|
||||||
}
|
d = 0;
|
||||||
*retDataSize = sizeof(DWORD);
|
}
|
||||||
if (value == Py_None) {
|
else if (PyLong_Check(value)) {
|
||||||
DWORD zero = 0;
|
d = PyLong_AsUnsignedLong(value);
|
||||||
memcpy(*retDataBuf, &zero, sizeof(DWORD));
|
if (d == (DWORD)(-1) && PyErr_Occurred()) {
|
||||||
}
|
return FALSE;
|
||||||
else {
|
}
|
||||||
DWORD d = PyLong_AsUnsignedLong(value);
|
}
|
||||||
|
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
|
||||||
|
if (*retDataBuf == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
memcpy(*retDataBuf, &d, sizeof(DWORD));
|
memcpy(*retDataBuf, &d, sizeof(DWORD));
|
||||||
|
*retDataSize = sizeof(DWORD);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
case REG_QWORD:
|
||||||
case REG_QWORD:
|
{
|
||||||
if (value != Py_None && !PyLong_Check(value))
|
if (value != Py_None && !PyLong_Check(value)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
*retDataBuf = (BYTE *)PyMem_NEW(DWORD64, 1);
|
}
|
||||||
if (*retDataBuf == NULL){
|
DWORD64 d;
|
||||||
PyErr_NoMemory();
|
if (value == Py_None) {
|
||||||
return FALSE;
|
d = 0;
|
||||||
}
|
}
|
||||||
*retDataSize = sizeof(DWORD64);
|
else if (PyLong_Check(value)) {
|
||||||
if (value == Py_None) {
|
d = PyLong_AsUnsignedLongLong(value);
|
||||||
DWORD64 zero = 0;
|
if (d == (DWORD64)(-1) && PyErr_Occurred()) {
|
||||||
memcpy(*retDataBuf, &zero, sizeof(DWORD64));
|
return FALSE;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
DWORD64 d = PyLong_AsUnsignedLongLong(value);
|
*retDataBuf = (BYTE *)PyMem_NEW(DWORD64, 1);
|
||||||
|
if (*retDataBuf == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
memcpy(*retDataBuf, &d, sizeof(DWORD64));
|
memcpy(*retDataBuf, &d, sizeof(DWORD64));
|
||||||
|
*retDataSize = sizeof(DWORD64);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case REG_SZ:
|
case REG_SZ:
|
||||||
case REG_EXPAND_SZ:
|
case REG_EXPAND_SZ:
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue