Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2833,6 +2833,8 @@ def test_cli_converters(self):
"uint64",
"uint8",
"unicode",
"unicode_fs_decoded",
"unicode_fs_encoded",
"unsigned_char",
"unsigned_int",
"unsigned_long",
Expand Down
15 changes: 15 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,21 @@ def test_compile_filename(self):
compile('pass', filename, 'exec')
self.assertRaises(TypeError, compile, 'pass', list(b'file.py'), 'exec')

def test_compile_filename_refleak(self):
# Regression tests for reference leak in PyUnicode_FSDecoder.
# See https://github.com/python/cpython/issues/139748.
mortal_str = 'this is a mortal string'
# check error path when 'mode' AC conversion failed
self.assertRaises(TypeError, compile, b'', mortal_str, mode=1234)
# check error path when 'optimize' AC conversion failed
self.assertRaises(OverflowError, compile, b'', mortal_str,
'exec', optimize=1 << 1000)
# check error path when 'dont_inherit' AC conversion failed
class EvilBool:
def __bool__(self): raise ValueError
self.assertRaises(ValueError, compile, b'', mortal_str,
'exec', dont_inherit=EvilBool())

@support.cpython_only
def test_same_filename_used(self):
s = """def f(): pass\ndef g(): pass"""
Expand Down
7 changes: 7 additions & 0 deletions Lib/test/test_symtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,13 @@ def test_symtable_entry_repr(self):
expected = f"<symtable entry top({self.top.get_id()}), line {self.top.get_lineno()}>"
self.assertEqual(repr(self.top._table), expected)

def test__symtable_refleak(self):
# Regression test for reference leak in PyUnicode_FSDecoder.
# See https://github.com/python/cpython/issues/139748.
mortal_str = 'this is a mortal string'
# check error path when 'compile_type' AC conversion failed
self.assertRaises(TypeError, symtable.symtable, '', mortal_str, 1)


class ComprehensionTests(unittest.TestCase):
def get_identifiers_recursive(self, st, res):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix reference leaks in error branches of functions accepting path strings or
bytes such as :func:`compile` and :func:`os.system`. Patch by Bénédikt Tran.
5 changes: 2 additions & 3 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1831,14 +1831,14 @@ _certificate_to_der(_sslmodulestate *state, X509 *certificate)

/*[clinic input]
_ssl._test_decode_cert
path: object(converter="PyUnicode_FSConverter")
path: unicode_fs_encoded
/

[clinic start generated code]*/

static PyObject *
_ssl__test_decode_cert_impl(PyObject *module, PyObject *path)
/*[clinic end generated code: output=96becb9abb23c091 input=cdeaaf02d4346628]*/
/*[clinic end generated code: output=96becb9abb23c091 input=cb4988d5e651a4f8]*/
{
PyObject *retval = NULL;
X509 *x=NULL;
Expand Down Expand Up @@ -1868,7 +1868,6 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path)
X509_free(x);

fail0:
Py_DECREF(path);
if (cert != NULL) BIO_free(cert);
return retval;
}
Expand Down
7 changes: 5 additions & 2 deletions Modules/clinic/_ssl.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Modules/clinic/socketmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Modules/clinic/symtablemodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 14 additions & 25 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3122,17 +3122,6 @@ class dev_t_return_converter(unsigned_long_return_converter):
conversion_fn = '_PyLong_FromDev'
unsigned_cast = '(dev_t)'

class FSConverter_converter(CConverter):
type = 'PyObject *'
converter = 'PyUnicode_FSConverter'
def converter_init(self):
if self.default is not unspecified:
fail("FSConverter_converter does not support default values")
self.c_default = 'NULL'

def cleanup(self):
return "Py_XDECREF(" + self.name + ");\n"

class pid_t_converter(CConverter):
type = 'pid_t'
format_unit = '" _Py_PARSE_PID "'
Expand Down Expand Up @@ -3196,7 +3185,7 @@ class confname_converter(CConverter):
""", argname=argname, converter=self.converter, table=self.table)

[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=8189d5ae78244626]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=d2759f2332cd39b3]*/

/*[clinic input]

Expand Down Expand Up @@ -6098,14 +6087,14 @@ os_system_impl(PyObject *module, const wchar_t *command)
/*[clinic input]
os.system -> long

command: FSConverter
command: unicode_fs_encoded

Execute the command in a subshell.
[clinic start generated code]*/

static long
os_system_impl(PyObject *module, PyObject *command)
/*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
/*[clinic end generated code: output=290fc437dd4f33a0 input=47c6f24b6dc92881]*/
{
long result;
const char *bytes = PyBytes_AsString(command);
Expand Down Expand Up @@ -9285,7 +9274,7 @@ os_getgroups_impl(PyObject *module)
/*[clinic input]
os.initgroups

username as oname: FSConverter
username as oname: unicode_fs_encoded
gid: int
/

Expand All @@ -9298,12 +9287,12 @@ group id.

static PyObject *
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
/*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
/*[clinic end generated code: output=7f074d30a425fd3a input=984e60c7fed88cb4]*/
#else
/*[clinic input]
os.initgroups

username as oname: FSConverter
username as oname: unicode_fs_encoded
gid: gid_t
/

Expand All @@ -9316,7 +9305,7 @@ group id.

static PyObject *
os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
/*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
/*[clinic end generated code: output=59341244521a9e3f input=17d8fbe2dea42ca4]*/
#endif
{
const char *username = PyBytes_AS_STRING(oname);
Expand Down Expand Up @@ -13067,16 +13056,16 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
/*[clinic input]
os.putenv

name: FSConverter
value: FSConverter
name: unicode_fs_encoded
value: unicode_fs_encoded
/

Change or add an environment variable.
[clinic start generated code]*/

static PyObject *
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
/*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
/*[clinic end generated code: output=d29a567d6b2327d2 input=84fcd30f873c8c45]*/
{
const char *name_string = PyBytes_AS_STRING(name);
const char *value_string = PyBytes_AS_STRING(value);
Expand Down Expand Up @@ -13119,15 +13108,15 @@ os_unsetenv_impl(PyObject *module, PyObject *name)
#else
/*[clinic input]
os.unsetenv
name: FSConverter
name: unicode_fs_encoded
/

Delete an environment variable.
[clinic start generated code]*/

static PyObject *
os_unsetenv_impl(PyObject *module, PyObject *name)
/*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
/*[clinic end generated code: output=54c4137ab1834f02 input=78ff12e505ade80a]*/
{
if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
return NULL;
Expand Down Expand Up @@ -15185,14 +15174,14 @@ os_urandom_impl(PyObject *module, Py_ssize_t size)
/*[clinic input]
os.memfd_create

name: FSConverter
name: unicode_fs_encoded
flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC

[clinic start generated code]*/

static PyObject *
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
/*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
/*[clinic end generated code: output=6681ede983bdb9a6 input=cd0eb092cfac474b]*/
{
int fd;
const char *bytes = PyBytes_AS_STRING(name);
Expand Down
5 changes: 2 additions & 3 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -7261,15 +7261,15 @@ Returns a list of network interface information (index, name) tuples.");

/*[clinic input]
_socket.if_nametoindex
oname: object(converter="PyUnicode_FSConverter")
oname: unicode_fs_encoded
/
Returns the interface index corresponding to the interface name if_name.
[clinic start generated code]*/

static PyObject *
_socket_if_nametoindex_impl(PyObject *module, PyObject *oname)
/*[clinic end generated code: output=289a411614f30244 input=01e0f1205307fb77]*/
/*[clinic end generated code: output=289a411614f30244 input=6125dc20683560cf]*/
{
#ifdef MS_WINDOWS
NET_IFINDEX index;
Expand All @@ -7278,7 +7278,6 @@ _socket_if_nametoindex_impl(PyObject *module, PyObject *oname)
#endif

index = if_nametoindex(PyBytes_AS_STRING(oname));
Py_DECREF(oname);
if (index == 0) {
/* if_nametoindex() doesn't set errno */
PyErr_SetString(PyExc_OSError, "no interface with this name");
Expand Down
6 changes: 2 additions & 4 deletions Modules/symtablemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module _symtable
_symtable.symtable

source: object
filename: object(converter='PyUnicode_FSDecoder')
filename: unicode_fs_decoded
startstr: str
/

Expand All @@ -23,7 +23,7 @@ Return symbol and scope dictionaries used internally by compiler.
static PyObject *
_symtable_symtable_impl(PyObject *module, PyObject *source,
PyObject *filename, const char *startstr)
/*[clinic end generated code: output=59eb0d5fc7285ac4 input=9dd8a50c0c36a4d7]*/
/*[clinic end generated code: output=59eb0d5fc7285ac4 input=436ffff90d02e4f6]*/
{
struct symtable *st;
PyObject *t;
Expand All @@ -47,12 +47,10 @@ _symtable_symtable_impl(PyObject *module, PyObject *source,
else {
PyErr_SetString(PyExc_ValueError,
"symtable() arg 3 must be 'exec' or 'eval' or 'single'");
Py_DECREF(filename);
Py_XDECREF(source_copy);
return NULL;
}
st = _Py_SymtableStringObjectFlags(str, filename, start, &cf);
Py_DECREF(filename);
Py_XDECREF(source_copy);
if (st == NULL) {
return NULL;
Expand Down
5 changes: 2 additions & 3 deletions Python/bltinmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ builtin_chr(PyObject *module, PyObject *i)
compile as builtin_compile

source: object
filename: object(converter="PyUnicode_FSDecoder")
filename: unicode_fs_decoded
mode: str
flags: int = 0
dont_inherit: bool = False
Expand All @@ -771,7 +771,7 @@ static PyObject *
builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
const char *mode, int flags, int dont_inherit,
int optimize, int feature_version)
/*[clinic end generated code: output=b0c09c84f116d3d7 input=cc78e20e7c7682ba]*/
/*[clinic end generated code: output=b0c09c84f116d3d7 input=8f0069edbdac381b]*/
{
PyObject *source_copy;
const char *str;
Expand Down Expand Up @@ -889,7 +889,6 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
error:
result = NULL;
finally:
Py_DECREF(filename);
return result;
}

Expand Down
7 changes: 5 additions & 2 deletions Python/clinic/bltinmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading