https://github.com/python/cpython/commit/55e16b74fd9f4fbafac43d7b51d5e3c87d2860dd
commit: 55e16b74fd9f4fbafac43d7b51d5e3c87d2860dd
branch: 3.13
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-12-09T16:46:24+02:00
summary:

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

(cherry picked from commit 3ec941b364778bce4fac6c6100730e120b426849)

Co-authored-by: Jeong, YunWon <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-12-05-18-26-50.gh-issue-142282.g6RQUN.rst
M Lib/test/test_winreg.py
M PC/winreg.c

diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py
index 924a962781a75b..1bc830c02c39ce 100644
--- a/Lib/test/test_winreg.py
+++ b/Lib/test/test_winreg.py
@@ -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
diff --git 
a/Misc/NEWS.d/next/Library/2025-12-05-18-26-50.gh-issue-142282.g6RQUN.rst 
b/Misc/NEWS.d/next/Library/2025-12-05-18-26-50.gh-issue-142282.g6RQUN.rst
new file mode 100644
index 00000000000000..d038cd40f4f57a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-12-05-18-26-50.gh-issue-142282.g6RQUN.rst
@@ -0,0 +1 @@
+Fix :func:`winreg.QueryValueEx` to not accidentally read garbage buffer under 
race condition.
diff --git a/PC/winreg.c b/PC/winreg.c
index ed2cce51cb709a..b81b0590eb9cb1 100644
--- a/PC/winreg.c
+++ b/PC/winreg.c
@@ -1660,7 +1660,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;

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to