Commit f59a088c authored by Jérome Perrin's avatar Jérome Perrin Committed by Xavier Thompson

[fix] Reject invalid options set by recipes

When recipes mutate the options, we should not allow invalid syntax
otherwise it gets written in .installed.cfg and generate invalid
configparser syntax.
parent d43512f2
...@@ -1806,6 +1806,8 @@ class Options(DictMixin): ...@@ -1806,6 +1806,8 @@ class Options(DictMixin):
return v return v
def __setitem__(self, option, value): def __setitem__(self, option, value):
if not re.match(zc.buildout.configparser.option_name_re + '$', option):
raise zc.buildout.UserError("Invalid option name %r" % (option, ))
if not isinstance(value, str): if not isinstance(value, str):
value = dumps(value) value = dumps(value)
self._data[option] = value.replace('${', '$${') self._data[option] = value.replace('${', '$${')
......
...@@ -113,10 +113,12 @@ section_header = re.compile( ...@@ -113,10 +113,12 @@ section_header = re.compile(
r'([#;].*)?$)' r'([#;].*)?$)'
).match ).match
option_name_re = r'[^\s{}[\]=:]+'
option_start = re.compile( option_start = re.compile(
r'(?P<name>[^\s{}[\]=:]+\s*[-+]?)' r'(?P<name>%s\s*[-+]?)'
r'=' r'='
r'(?P<value>.*)$').match r'(?P<value>.*)$'
% option_name_re).match
leading_blank_lines = re.compile(r"^(\s*\n)+") leading_blank_lines = re.compile(r"^(\s*\n)+")
......
...@@ -2391,6 +2391,53 @@ def test_recipe_options_are_escaped(): ...@@ -2391,6 +2391,53 @@ def test_recipe_options_are_escaped():
recipe = recipes:test recipe = recipes:test
""" """
def test_recipe_invalid_options_are_rejected():
r"""
>>> mkdir(sample_buildout, 'recipes')
>>> write(sample_buildout, 'recipes', 'test.py',
... '''
... class Recipe:
...
... def __init__(self, buildout, name, options):
... options['[section]\\noption'] = 'invalid'
...
... def install(self):
... return ()
...
... update = install
... ''')
>>> write(sample_buildout, 'recipes', 'setup.py',
... '''
... from setuptools import setup
... setup(
... name = "recipes",
... entry_points = {'zc.buildout': ['test = test:Recipe']},
... )
... ''')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... develop = recipes
... parts = a
... [a]
... recipe = recipes:test
... ''')
>>> os.chdir(sample_buildout)
>>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
>>> print_(system(buildout), end='')
Develop: '/sample-buildout/recipes'
While:
Installing.
Getting section a.
Initializing section a.
Error: Invalid option name '[section]\noption'
"""
def read_find_links_to_load_extensions(): def read_find_links_to_load_extensions():
r""" r"""
We'll create a wacky buildout extension that just announces itself when used: We'll create a wacky buildout extension that just announces itself when used:
......
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