From f656cf42d2012be21043a95bc66bea9221629545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Verg=C3=A9?= Date: Tue, 27 Sep 2016 09:27:36 +0200 Subject: [PATCH] fix(line-length): Wrap token scanning securely With `allow-non-breakable-inline-mappings` enabled, every long line is passed through `loader.peek_token()`. Even lines that are not valid YAML. For this reason, this code must be wrapped in a `try`/`except` block. Closes: #21 --- tests/rules/test_line_length.py | 10 ++++++++++ yamllint/rules/line_length.py | 19 ++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/tests/rules/test_line_length.py b/tests/rules/test_line_length.py index 2212c3f..be1115e 100644 --- a/tests/rules/test_line_length.py +++ b/tests/rules/test_line_length.py @@ -32,6 +32,9 @@ class LineLengthTestCase(RuleTestCase): self.check('---\n' + 81 * 'a' + '\n', conf) self.check(1000 * 'b', conf) self.check('---\n' + 1000 * 'b' + '\n', conf) + self.check('content: |\n' + ' {% this line is' + 99 * ' really' + ' long %}\n', + conf) def test_default(self): conf = ('line-length: {max: 80}\n' @@ -145,3 +148,10 @@ class LineLengthTestCase(RuleTestCase): self.check('---\n' '- long line: and+some+space+at+the+end \n', conf, problem=(2, 21)) + + # See https://github.com/adrienverge/yamllint/issues/21 + conf = 'line-length: {allow-non-breakable-inline-mappings: yes}' + self.check('---\n' + 'content: |\n' + ' {% this line is' + 99 * ' really' + ' long %}\n', + conf, problem=(3, 81)) diff --git a/yamllint/rules/line_length.py b/yamllint/rules/line_length.py index 09e8b23..a0c0b37 100644 --- a/yamllint/rules/line_length.py +++ b/yamllint/rules/line_length.py @@ -102,13 +102,18 @@ CONF = {'max': int, def check_inline_mapping(line): loader = yaml.SafeLoader(line.content) - while loader.peek_token(): - if isinstance(loader.get_token(), yaml.BlockMappingStartToken): - while loader.peek_token(): - if isinstance(loader.get_token(), yaml.ValueToken): - t = loader.get_token() - if isinstance(t, yaml.ScalarToken): - return ' ' not in line.content[t.start_mark.column:] + try: + while loader.peek_token(): + if isinstance(loader.get_token(), yaml.BlockMappingStartToken): + while loader.peek_token(): + if isinstance(loader.get_token(), yaml.ValueToken): + t = loader.get_token() + if isinstance(t, yaml.ScalarToken): + return ( + ' ' not in line.content[t.start_mark.column:]) + except yaml.scanner.ScannerError: + pass + return False