mirror of
https://github.com/certbot/certbot.git
synced 2026-08-03 16:12:13 +02:00
Fix nginx parser crash on comments inside multi-line directives (#10598)
This commit is contained in:
@@ -13,6 +13,7 @@ from typing import SupportsIndex
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from pyparsing import Combine
|
from pyparsing import Combine
|
||||||
|
from pyparsing import FollowedBy
|
||||||
from pyparsing import Forward
|
from pyparsing import Forward
|
||||||
from pyparsing import Group
|
from pyparsing import Group
|
||||||
from pyparsing import Literal
|
from pyparsing import Literal
|
||||||
@@ -50,15 +51,29 @@ class RawNginxParser:
|
|||||||
|
|
||||||
token = paren_quote_extend | tokenchars | quoted
|
token = paren_quote_extend | tokenchars | quoted
|
||||||
|
|
||||||
whitespace_token_group = space + token + ZeroOrMore(required_space + token) + space
|
# An nginx comment runs from '#' to the end of the line. `restOfLine` does
|
||||||
assignment = whitespace_token_group + semicolon
|
# not consume the trailing newline; the following `required_space` does.
|
||||||
|
comment = Literal('#') + restOfLine
|
||||||
|
# A separator between two tokens is whitespace, optionally interleaved with
|
||||||
|
# one or more comments. The `FollowedBy(token)` lookahead means a comment is
|
||||||
|
# only treated as inline when a real token follows it — otherwise we leave
|
||||||
|
# the `#` alone so existing fallback paths (e.g. comment-as-token in a block
|
||||||
|
# header) still parse. This lets a multi-line directive contain comment
|
||||||
|
# lines between its tokens (valid nginx), which the old grammar mis-parsed:
|
||||||
|
# an unbalanced `"` inside such a comment would be sucked up by the
|
||||||
|
# `multiline=True` quoted strings and run away across the rest of the file
|
||||||
|
# (issue #10598).
|
||||||
|
token_separator = required_space + ZeroOrMore(
|
||||||
|
comment + required_space + FollowedBy(token)
|
||||||
|
)
|
||||||
|
|
||||||
comment = space + Literal('#') + restOfLine
|
whitespace_token_group = space + token + ZeroOrMore(token_separator + token) + space
|
||||||
|
assignment = whitespace_token_group + semicolon
|
||||||
|
|
||||||
block = Forward()
|
block = Forward()
|
||||||
|
|
||||||
# order matters! see issue 518, and also http { # server { \n}
|
# order matters! see issue 518, and also http { # server { \n}
|
||||||
contents = Group(comment) | Group(block) | Group(assignment)
|
contents = Group(space + comment) | Group(block) | Group(assignment)
|
||||||
|
|
||||||
block_begin = Group(whitespace_token_group)
|
block_begin = Group(whitespace_token_group)
|
||||||
block_innards = Group(ZeroOrMore(contents) + space).leave_whitespace()
|
block_innards = Group(ZeroOrMore(contents) + space).leave_whitespace()
|
||||||
|
|||||||
@@ -201,6 +201,20 @@ class TestRawNginxParser(unittest.TestCase):
|
|||||||
[['#', ' server{']]]
|
[['#', ' server{']]]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def test_comment_inside_multiline_directive(self):
|
||||||
|
# See https://github.com/certbot/certbot/issues/10598
|
||||||
|
# An unbalanced double-quote inside a comment that sits between tokens
|
||||||
|
# of a multi-line directive must not be sucked into a multiline quoted
|
||||||
|
# string and run away across the rest of the file.
|
||||||
|
source = ("http {\n"
|
||||||
|
" log_format json_test escape=json '{'\n"
|
||||||
|
" # '\"req\": \"$request\"' # GET \"/test?...\n"
|
||||||
|
" '}';\n"
|
||||||
|
"}\n")
|
||||||
|
parsed = loads(source)
|
||||||
|
# The config parses and round-trips byte-for-byte.
|
||||||
|
assert dumps(parsed) == source
|
||||||
|
|
||||||
def test_access_log(self):
|
def test_access_log(self):
|
||||||
# see issue #3798
|
# see issue #3798
|
||||||
parsed = loads('access_log syslog:server=unix:/dev/log,facility=auth,'
|
parsed = loads('access_log syslog:server=unix:/dev/log,facility=auth,'
|
||||||
|
|||||||
Reference in New Issue
Block a user