Skip to content

Commit f54773f

Browse files
committed
gh-148798: fix crash in _interpreters.create on surrogate str in config
_config_dict_copy_str passed the result of PyUnicode_AsUTF8 straight to strncpy. When the string contained an unpaired surrogate, PyUnicode_AsUTF8 returned NULL and set UnicodeEncodeError, and strncpy dereferenced NULL. Check the return value and propagate the error, mirroring the pattern used at Modules/_interpretersmodule.c:425. Add a regression test alongside the existing gh-126221 case.
1 parent a00b24e commit f54773f

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

Lib/test/test_interpreters/test_api.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ def test_in_main(self):
117117
# GH-126221: Passing an invalid Unicode character used to cause a SystemError
118118
self.assertRaises(UnicodeEncodeError, _interpreters.create, '\udc80')
119119

120+
# A config object with a surrogate in a string field must raise, not crash.
121+
class BadConfig:
122+
use_main_obmalloc = False
123+
allow_fork = False
124+
allow_exec = False
125+
allow_threads = False
126+
allow_daemon_threads = False
127+
check_multi_interp_extensions = False
128+
own_gil = True
129+
gil = 'own\udc80'
130+
self.assertRaises(UnicodeEncodeError, _interpreters.create, BadConfig())
131+
120132
def test_in_thread(self):
121133
lock = threading.Lock()
122134
interp = None
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix a crash in :func:`!_interpreters.create` when a config object passes a
2+
string with an unpaired surrogate as a value (for example ``gil``). The
3+
internal helper ``_config_dict_copy_str`` now checks the return of
4+
:c:func:`PyUnicode_AsUTF8` before copying, turning the segfault into a
5+
:exc:`UnicodeEncodeError`.

Python/interpconfig.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,12 @@ _config_dict_copy_str(PyObject *dict, const char *name,
133133
config_dict_invalid_type(name);
134134
return -1;
135135
}
136-
strncpy(buf, PyUnicode_AsUTF8(item), bufsize-1);
136+
const char *utf8 = PyUnicode_AsUTF8(item);
137+
if (utf8 == NULL) {
138+
Py_DECREF(item);
139+
return -1;
140+
}
141+
strncpy(buf, utf8, bufsize-1);
137142
buf[bufsize-1] = '\0';
138143
Py_DECREF(item);
139144
return 0;

0 commit comments

Comments
 (0)