Commit d52e3d4a authored by Larry Hastings's avatar Larry Hastings

Issue #19390: Argument Clinic no longer accepts malformed Python and C ids.

parent 25a49626
...@@ -129,6 +129,11 @@ Build ...@@ -129,6 +129,11 @@ Build
- Issue #19356: Avoid using a C variabled named "_self", it's a reserved - Issue #19356: Avoid using a C variabled named "_self", it's a reserved
word in some C compilers. word in some C compilers.
Tools/Demos
-----------
- Issue #19390: Argument Clinic no longer accepts malformed Python
and C ids.
What's New in Python 3.4.0 Alpha 4? What's New in Python 3.4.0 Alpha 4?
=================================== ===================================
......
...@@ -122,6 +122,11 @@ def quoted_for_c_string(s): ...@@ -122,6 +122,11 @@ def quoted_for_c_string(s):
s = s.replace(old, new) s = s.replace(old, new)
return s return s
is_legal_c_identifier = re.compile('^[A-Za-z_][A-Za-z0-9_]*$').match
def is_legal_py_identifier(s):
return all(is_legal_c_identifier(field) for field in s.split('.'))
# added "self", "cls", and "null" just to be safe # added "self", "cls", and "null" just to be safe
# (clinic will generate variables with these names) # (clinic will generate variables with these names)
c_keywords = set(""" c_keywords = set("""
...@@ -131,8 +136,11 @@ return self short signed sizeof static struct switch typedef ...@@ -131,8 +136,11 @@ return self short signed sizeof static struct switch typedef
typeof union unsigned void volatile while typeof union unsigned void volatile while
""".strip().split()) """.strip().split())
def legal_c_identifier(s): def ensure_legal_c_identifier(s):
# if we picked a C keyword, pick something else # for now, just complain if what we're given isn't legal
if not is_legal_c_identifier(s):
fail("Illegal C identifier: {}".format(s))
# but if we picked a C keyword, pick something else
if s in c_keywords: if s in c_keywords:
return s + "_value" return s + "_value"
return s return s
...@@ -1311,7 +1319,7 @@ class CConverter(metaclass=CConverterAutoRegister): ...@@ -1311,7 +1319,7 @@ class CConverter(metaclass=CConverterAutoRegister):
parameter is a clinic.Parameter instance. parameter is a clinic.Parameter instance.
data is a CRenderData instance. data is a CRenderData instance.
""" """
name = legal_c_identifier(self.name) name = ensure_legal_c_identifier(self.name)
# declarations # declarations
d = self.declaration() d = self.declaration()
...@@ -1359,7 +1367,7 @@ class CConverter(metaclass=CConverterAutoRegister): ...@@ -1359,7 +1367,7 @@ class CConverter(metaclass=CConverterAutoRegister):
if self.encoding: if self.encoding:
list.append(self.encoding) list.append(self.encoding)
s = ("&" if self.parse_by_reference else "") + legal_c_identifier(self.name) s = ("&" if self.parse_by_reference else "") + ensure_legal_c_identifier(self.name)
list.append(s) list.append(s)
# #
...@@ -1377,7 +1385,7 @@ class CConverter(metaclass=CConverterAutoRegister): ...@@ -1377,7 +1385,7 @@ class CConverter(metaclass=CConverterAutoRegister):
prototype.append(" ") prototype.append(" ")
if by_reference: if by_reference:
prototype.append('*') prototype.append('*')
prototype.append(legal_c_identifier(self.name)) prototype.append(ensure_legal_c_identifier(self.name))
return "".join(prototype) return "".join(prototype)
def declaration(self): def declaration(self):
...@@ -1575,7 +1583,7 @@ class Py_buffer_converter(CConverter): ...@@ -1575,7 +1583,7 @@ class Py_buffer_converter(CConverter):
self.format_unit = 'z*' if nullable else 's*' self.format_unit = 'z*' if nullable else 's*'
def cleanup(self): def cleanup(self):
return "PyBuffer_Release(&" + legal_c_identifier(self.name) + ");\n" return "PyBuffer_Release(&" + ensure_legal_c_identifier(self.name) + ");\n"
def add_c_return_converter(f, name=None): def add_c_return_converter(f, name=None):
...@@ -1895,6 +1903,11 @@ class DSLParser: ...@@ -1895,6 +1903,11 @@ class DSLParser:
full_name = full_name.strip() full_name = full_name.strip()
c_basename = c_basename.strip() or None c_basename = c_basename.strip() or None
if not is_legal_py_identifier(full_name):
fail("Illegal function name: {}".format(full_name))
if c_basename and not is_legal_c_identifier(c_basename):
fail("Illegal C basename: {}".format(c_basename))
if not returns: if not returns:
return_converter = CReturnConverter() return_converter = CReturnConverter()
else: else:
......
...@@ -560,6 +560,20 @@ Docstring ...@@ -560,6 +560,20 @@ Docstring
self.assertEqual("Docstring\n\nfoo.bar()", function.docstring) self.assertEqual("Docstring\n\nfoo.bar()", function.docstring)
self.assertEqual(0, len(function.parameters)) self.assertEqual(0, len(function.parameters))
def test_illegal_module_line(self):
self.parse_function_should_fail("""
module foo
foo.bar => int
/
""")
def test_illegal_c_basename(self):
self.parse_function_should_fail("""
module foo
foo.bar as 935
/
""")
def test_single_star(self): def test_single_star(self):
self.parse_function_should_fail(""" self.parse_function_should_fail("""
module foo module foo
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment