summaryrefslogtreecommitdiffstats
path: root/Tools
diff options
context:
space:
mode:
authorcolorfulappl <colorfulappl@qq.com>2022-11-24 14:01:26 (GMT)
committerGitHub <noreply@github.com>2022-11-24 14:01:26 (GMT)
commit8dbe08eb7c807f484fe9870f5b7f5ae2881fd966 (patch)
treee8a735022f12ba4a1b73dc2449d6e5e40383bded /Tools
parent69f6cc77d0f1664f983a83b6ae707d99a99f5c4f (diff)
downloadcpython-8dbe08eb7c807f484fe9870f5b7f5ae2881fd966.zip
cpython-8dbe08eb7c807f484fe9870f5b7f5ae2881fd966.tar.gz
cpython-8dbe08eb7c807f484fe9870f5b7f5ae2881fd966.tar.bz2
gh-99240: Fix double-free bug in Argument Clinic str_converter generated code (GH-99241)
Fix double-free bug mentioned at https://github.com/python/cpython/issues/99240, by moving memory clean up out of "exit" label. Automerge-Triggered-By: GH:erlend-aasland
Diffstat (limited to 'Tools')
-rwxr-xr-xTools/clinic/clinic.py25
1 files changed, 23 insertions, 2 deletions
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 94e17ee..0117a50 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -348,6 +348,12 @@ class CRenderData:
# "goto exit" if there are any.
self.return_conversion = []
+ # The C statements required to do some operations
+ # after the end of parsing but before cleaning up.
+ # These operations may be, for example, memory deallocations which
+ # can only be done without any error happening during argument parsing.
+ self.post_parsing = []
+
# The C statements required to clean up after the impl call.
self.cleanup = []
@@ -820,6 +826,7 @@ class CLanguage(Language):
{modifications}
{return_value} = {c_basename}_impl({impl_arguments});
{return_conversion}
+ {post_parsing}
{exit_label}
{cleanup}
@@ -1460,6 +1467,7 @@ class CLanguage(Language):
template_dict['impl_parameters'] = ", ".join(data.impl_parameters)
template_dict['impl_arguments'] = ", ".join(data.impl_arguments)
template_dict['return_conversion'] = format_escape("".join(data.return_conversion).rstrip())
+ template_dict['post_parsing'] = format_escape("".join(data.post_parsing).rstrip())
template_dict['cleanup'] = format_escape("".join(data.cleanup))
template_dict['return_value'] = data.return_value
@@ -1484,6 +1492,7 @@ class CLanguage(Language):
return_conversion=template_dict['return_conversion'],
initializers=template_dict['initializers'],
modifications=template_dict['modifications'],
+ post_parsing=template_dict['post_parsing'],
cleanup=template_dict['cleanup'],
)
@@ -2725,6 +2734,10 @@ class CConverter(metaclass=CConverterAutoRegister):
# parse_arguments
self.parse_argument(data.parse_arguments)
+ # post_parsing
+ if post_parsing := self.post_parsing():
+ data.post_parsing.append('/* Post parse cleanup for ' + name + ' */\n' + post_parsing.rstrip() + '\n')
+
# cleanup
cleanup = self.cleanup()
if cleanup:
@@ -2820,6 +2833,14 @@ class CConverter(metaclass=CConverterAutoRegister):
"""
return ""
+ def post_parsing(self):
+ """
+ The C statements required to do some operations after the end of parsing but before cleaning up.
+ Return a string containing this code indented at column 0.
+ If no operation is necessary, return an empty string.
+ """
+ return ""
+
def cleanup(self):
"""
The C statements required to clean up after this variable.
@@ -3416,10 +3437,10 @@ class str_converter(CConverter):
if NoneType in accept and self.c_default == "Py_None":
self.c_default = "NULL"
- def cleanup(self):
+ def post_parsing(self):
if self.encoding:
name = self.name
- return "".join(["if (", name, ") {\n PyMem_FREE(", name, ");\n}\n"])
+ return f"PyMem_FREE({name});\n"
def parse_arg(self, argname, displayname):
if self.format_unit == 's':