[3.14] gh-142282 Fix winreg.QueryValueEx() under race condition (GH-142283) (GH-142453)

(cherry picked from commit 3ec941b364)

Co-authored-by: Jeong, YunWon <69878+youknowone@users.noreply.github.com>
This commit is contained in:
Miss Islington (bot) 2025-12-09 13:33:35 +01:00 committed by GitHub
parent f200776b13
commit 19968c8927
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 34 additions and 1 deletions

View file

@ -3,6 +3,7 @@
import gc
import os, sys, errno
import itertools
import threading
import unittest
from platform import machine, win32_edition
@ -291,6 +292,37 @@ def run(self):
DeleteKey(HKEY_CURRENT_USER, test_key_name+'\\changing_value')
DeleteKey(HKEY_CURRENT_USER, test_key_name)
def test_queryvalueex_race_condition(self):
# gh-142282: QueryValueEx could read garbage buffer under race
# condition when another thread changes the value size
done = False
ready = threading.Event()
values = [b'ham', b'spam']
class WriterThread(threading.Thread):
def run(self):
with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
values_iter = itertools.cycle(values)
while not done:
val = next(values_iter)
SetValueEx(key, 'test_value', 0, REG_BINARY, val)
ready.set()
thread = WriterThread()
thread.start()
try:
ready.wait()
with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
for _ in range(1000):
result, typ = QueryValueEx(key, 'test_value')
# The result must be one of the written values,
# not garbage data from uninitialized buffer
self.assertIn(result, values)
finally:
done = True
thread.join()
DeleteKey(HKEY_CURRENT_USER, test_key_name)
def test_long_key(self):
# Issue2810, in 2.6 and 3.1 when the key name was exactly 256
# characters, EnumKey raised "WindowsError: More data is

View file

@ -0,0 +1 @@
Fix :func:`winreg.QueryValueEx` to not accidentally read garbage buffer under race condition.

View file

@ -1681,7 +1681,7 @@ winreg_QueryValueEx_impl(PyObject *module, HKEY key, const wchar_t *name)
return PyErr_SetFromWindowsErrWithFunction(rc,
"RegQueryValueEx");
}
obData = Reg2Py(retBuf, bufSize, typ);
obData = Reg2Py(retBuf, retSize, typ);
PyMem_Free(retBuf);
if (obData == NULL)
return NULL;