Skip to content

Commit 3ec941b

Browse files
authored
gh-142282 Fix winreg.QueryValueEx() under race condition (GH-142283)
1 parent 756e7d1 commit 3ec941b

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

Lib/test/test_winreg.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import gc
55
import os, sys, errno
6+
import itertools
67
import threading
78
import unittest
89
from platform import machine, win32_edition
@@ -318,6 +319,37 @@ def run(self):
318319
DeleteKey(HKEY_CURRENT_USER, test_key_name+'\\changing_value')
319320
DeleteKey(HKEY_CURRENT_USER, test_key_name)
320321

322+
def test_queryvalueex_race_condition(self):
323+
# gh-142282: QueryValueEx could read garbage buffer under race
324+
# condition when another thread changes the value size
325+
done = False
326+
ready = threading.Event()
327+
values = [b'ham', b'spam']
328+
329+
class WriterThread(threading.Thread):
330+
def run(self):
331+
with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
332+
values_iter = itertools.cycle(values)
333+
while not done:
334+
val = next(values_iter)
335+
SetValueEx(key, 'test_value', 0, REG_BINARY, val)
336+
ready.set()
337+
338+
thread = WriterThread()
339+
thread.start()
340+
try:
341+
ready.wait()
342+
with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
343+
for _ in range(1000):
344+
result, typ = QueryValueEx(key, 'test_value')
345+
# The result must be one of the written values,
346+
# not garbage data from uninitialized buffer
347+
self.assertIn(result, values)
348+
finally:
349+
done = True
350+
thread.join()
351+
DeleteKey(HKEY_CURRENT_USER, test_key_name)
352+
321353
def test_long_key(self):
322354
# Issue2810, in 2.6 and 3.1 when the key name was exactly 256
323355
# characters, EnumKey raised "WindowsError: More data is
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix :func:`winreg.QueryValueEx` to not accidentally read garbage buffer under race condition.

PC/winreg.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,7 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const wchar_t *name)
16511651
return PyErr_SetFromWindowsErrWithFunction(rc,
16521652
"RegQueryValueEx");
16531653
}
1654-
obData = Reg2Py(retBuf, bufSize, typ);
1654+
obData = Reg2Py(retBuf, retSize, typ);
16551655
PyMem_Free(retBuf);
16561656
if (obData == NULL)
16571657
return NULL;

0 commit comments

Comments
 (0)