Skip to content

Commit dfcd467

Browse files
committed
Issue #19390: Argument Clinic no longer accepts malformed Python and C ids.
1 parent 186729e commit dfcd467

File tree

3 files changed

+38
-6
lines changed

3 files changed

+38
-6
lines changed

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,11 @@ Build
129129
- Issue #19356: Avoid using a C variabled named "_self", it's a reserved
130130
word in some C compilers.
131131

132+
Tools/Demos
133+
-----------
134+
135+
- Issue #19390: Argument Clinic no longer accepts malformed Python
136+
and C ids.
132137

133138
What's New in Python 3.4.0 Alpha 4?
134139
===================================

Tools/clinic/clinic.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ def quoted_for_c_string(s):
122122
s = s.replace(old, new)
123123
return s
124124

125+
is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
126+
127+
def is_legal_py_identifier(s):
128+
return all(is_legal_c_identifier(field) for field in s.split('.'))
129+
125130
# added "self", "cls", and "null" just to be safe
126131
# (clinic will generate variables with these names)
127132
c_keywords = set("""
@@ -131,8 +136,11 @@ def quoted_for_c_string(s):
131136
typeof union unsigned void volatile while
132137
""".strip().split())
133138

134-
def legal_c_identifier(s):
135-
# if we picked a C keyword, pick something else
139+
def ensure_legal_c_identifier(s):
140+
# for now, just complain if what we're given isn't legal
141+
if not is_legal_c_identifier(s):
142+
fail("Illegal C identifier: {}".format(s))
143+
# but if we picked a C keyword, pick something else
136144
if s in c_keywords:
137145
return s + "_value"
138146
return s
@@ -1311,7 +1319,7 @@ def render(self, parameter, data):
13111319
parameter is a clinic.Parameter instance.
13121320
data is a CRenderData instance.
13131321
"""
1314-
name = legal_c_identifier(self.name)
1322+
name = ensure_legal_c_identifier(self.name)
13151323

13161324
# declarations
13171325
d = self.declaration()
@@ -1359,7 +1367,7 @@ def parse_argument(self, list):
13591367
if self.encoding:
13601368
list.append(self.encoding)
13611369

1362-
s = ("&" if self.parse_by_reference else "") + legal_c_identifier(self.name)
1370+
s = ("&" if self.parse_by_reference else "") + ensure_legal_c_identifier(self.name)
13631371
list.append(s)
13641372

13651373
#
@@ -1377,7 +1385,7 @@ def simple_declaration(self, by_reference=False):
13771385
prototype.append(" ")
13781386
if by_reference:
13791387
prototype.append('*')
1380-
prototype.append(legal_c_identifier(self.name))
1388+
prototype.append(ensure_legal_c_identifier(self.name))
13811389
return "".join(prototype)
13821390

13831391
def declaration(self):
@@ -1575,7 +1583,7 @@ def converter_init(self, *, str=False, zeroes=False, nullable=False, read_write=
15751583
self.format_unit = 'z*' if nullable else 's*'
15761584

15771585
def cleanup(self):
1578-
return "PyBuffer_Release(&" + legal_c_identifier(self.name) + ");\n"
1586+
return "PyBuffer_Release(&" + ensure_legal_c_identifier(self.name) + ");\n"
15791587

15801588

15811589
def add_c_return_converter(f, name=None):
@@ -1895,6 +1903,11 @@ def state_modulename_name(self, line):
18951903
full_name = full_name.strip()
18961904
c_basename = c_basename.strip() or None
18971905

1906+
if not is_legal_py_identifier(full_name):
1907+
fail("Illegal function name: {}".format(full_name))
1908+
if c_basename and not is_legal_c_identifier(c_basename):
1909+
fail("Illegal C basename: {}".format(c_basename))
1910+
18981911
if not returns:
18991912
return_converter = CReturnConverter()
19001913
else:

Tools/clinic/clinic_test.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,20 @@ def test_no_parameters(self):
560560
self.assertEqual("Docstring\n\nfoo.bar()", function.docstring)
561561
self.assertEqual(0, len(function.parameters))
562562

563+
def test_illegal_module_line(self):
564+
self.parse_function_should_fail("""
565+
module foo
566+
foo.bar => int
567+
/
568+
""")
569+
570+
def test_illegal_c_basename(self):
571+
self.parse_function_should_fail("""
572+
module foo
573+
foo.bar as 935
574+
/
575+
""")
576+
563577
def test_single_star(self):
564578
self.parse_function_should_fail("""
565579
module foo

0 commit comments

Comments
 (0)