diff options
author | colorfulappl <colorfulappl@qq.com> | 2022-11-24 14:01:26 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-24 14:01:26 (GMT) |
commit | 8dbe08eb7c807f484fe9870f5b7f5ae2881fd966 (patch) | |
tree | e8a735022f12ba4a1b73dc2449d6e5e40383bded /Tools | |
parent | 69f6cc77d0f1664f983a83b6ae707d99a99f5c4f (diff) | |
download | cpython-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-x | Tools/clinic/clinic.py | 25 |
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': |