Skip to content

Commit 8e2e55e

Browse files
committed
test_queryvalueex_race_condition
1 parent ae60654 commit 8e2e55e

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

Lib/test/test_winreg.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,46 @@ def run(self):
318318
DeleteKey(HKEY_CURRENT_USER, test_key_name+'\\changing_value')
319319
DeleteKey(HKEY_CURRENT_USER, test_key_name)
320320

321+
def test_queryvalueex_race_condition(self):
322+
# gh-142282: QueryValueEx could read garbage buffer under race
323+
# condition when another thread changes the value size
324+
done = False
325+
error_found = None
326+
values = [b'ham', b'spam']
327+
328+
class WriterThread(threading.Thread):
329+
def run(self):
330+
with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
331+
use_first = True
332+
while not done:
333+
val = values[0] if use_first else values[1]
334+
use_first = not use_first
335+
SetValueEx(key, 'test_value', 0, REG_BINARY, val)
336+
337+
thread = WriterThread()
338+
thread.start()
339+
try:
340+
with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
341+
for _ in range(1000):
342+
try:
343+
result, typ = QueryValueEx(key, 'test_value')
344+
except FileNotFoundError:
345+
# Value not yet created
346+
continue
347+
# The result must be one of the written values,
348+
# not garbage data from uninitialized buffer
349+
if result not in values:
350+
error_found = result
351+
break
352+
finally:
353+
done = True
354+
thread.join()
355+
DeleteKey(HKEY_CURRENT_USER, test_key_name)
356+
357+
if error_found is not None:
358+
self.fail(f"QueryValueEx returned unexpected value: {error_found!r}, "
359+
f"expected one of {values}")
360+
321361
def test_long_key(self):
322362
# Issue2810, in 2.6 and 3.1 when the key name was exactly 256
323363
# characters, EnumKey raised "WindowsError: More data is

0 commit comments

Comments
 (0)