Skip to content

Commit 092fe89

Browse files
committed
fix: bugs with braces and semicolons in quoted strings
1 parent ae47080 commit 092fe89

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

nginx.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -444,43 +444,44 @@ def loads(data, conf=True):
444444
index += m.end()
445445
continue
446446

447-
m = re.compile(r'^\s*location\s*([^;]*?)\s*{', re.S).search(data[index:])
448-
if m:
447+
n = re.compile(r'(?!\B"[^"]*);(?![^"]*"\B)')
448+
m = re.compile(r'^\s*location\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
449+
if m and not n.search(m.group()):
449450
l = Location(m.group(1))
450451
lopen.insert(0, l)
451452
index += m.end()
452453
continue
453454

454-
m = re.compile(r'^\s*if\s*([^;]*?)\s*{', re.S).search(data[index:])
455-
if m:
455+
m = re.compile(r'^\s*if\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
456+
if m and not n.search(m.group()):
456457
ifs = If(m.group(1))
457458
lopen.insert(0, ifs)
458459
index += m.end()
459460
continue
460461

461-
m = re.compile(r'^\s*upstream\s*([^;]*?)\s*{', re.S).search(data[index:])
462-
if m:
462+
m = re.compile(r'^\s*upstream\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
463+
if m and not n.search(m.group()):
463464
u = Upstream(m.group(1))
464465
lopen.insert(0, u)
465466
index += m.end()
466467
continue
467468

468-
m = re.compile(r'^\s*geo\s*([^;]*?)\s*{', re.S).search(data[index:])
469-
if m:
469+
m = re.compile(r'^\s*geo\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
470+
if m and not n.search(m.group()):
470471
g = Geo(m.group(1))
471472
lopen.insert(0, g)
472473
index += m.end()
473474
continue
474475

475-
m = re.compile(r'^\s*map\s*([^;]*?)\s*{', re.S).search(data[index:])
476-
if m:
476+
m = re.compile(r'^\s*map\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
477+
if m and not n.search(m.group()):
477478
g = Map(m.group(1))
478479
lopen.insert(0, g)
479480
index += m.end()
480481
continue
481482

482-
m = re.compile(r'^\s*limit_except\s*([^;]*?)\s*{', re.S).search(data[index:])
483-
if m:
483+
m = re.compile(r'^\s*limit_except\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
484+
if m and not n.search(m.group()):
484485
l = LimitExcept(m.group(1))
485486
lopen.insert(0, l)
486487
index += m.end()

tests.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@
167167
location test9 {
168168
add_header X-XSS-Protection "1;mode-block";
169169
}
170+
171+
if ( $http_user_agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" ) {
172+
return 403;
173+
}
170174
"""
171175

172176
TESTBLOCK_CASE_10 = """
@@ -194,6 +198,21 @@
194198
}
195199
"""
196200

201+
TESTBLOCK_CASE_12 = """
202+
server {
203+
listen 80;
204+
server_name test.example.com;
205+
206+
location ~ "^/(test|[0-9a-zA-Z]{6})$" {
207+
if ($query_string ~ pid=(111)) {
208+
return 403;
209+
}
210+
211+
proxy_pass http://127.0.0.1:81;
212+
}
213+
}
214+
"""
215+
197216

198217
class TestPythonNginx(unittest.TestCase):
199218
def test_basic_load(self):
@@ -298,6 +317,8 @@ def test_semicolon_in_second_key_value(self):
298317
self.assertEqual(len(location_children), 1)
299318
self.assertEqual(location_children[0].name, "add_header")
300319
self.assertEqual(location_children[0].value, 'X-XSS-Protection "1;mode-block"')
320+
self.assertEqual(len(inp_data.filter("If")), 1)
321+
self.assertEqual(inp_data.filter("If")[0].value, "( $http_user_agent = \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)\" )")
301322

302323
def test_types_block(self):
303324
inp_data = nginx.loads(TESTBLOCK_CASE_10)
@@ -311,6 +332,11 @@ def test_missing_semi_colon(self):
311332
with pytest.raises(nginx.ParseError) as e:
312333
nginx.loads(TESTBLOCK_CASE_11)
313334
self.assertEqual(str(e.value), "Config syntax, missing ';' at index: 189")
335+
336+
def test_brace_inside_block_param(self):
337+
inp_data = nginx.loads(TESTBLOCK_CASE_12)
338+
self.assertEqual(len(inp_data.server.filter("Location")), 1)
339+
self.assertEqual(inp_data.server.filter("Location")[0].value, "~ \"^/(test|[0-9a-zA-Z]{6})$\"")
314340

315341

316342
if __name__ == '__main__':

0 commit comments

Comments
 (0)