Skip to content

Commit dda56d5

Browse files
committed
fix: bugs when using empty quotes in a key value
1 parent 65bace0 commit dda56d5

File tree

2 files changed

+40
-17
lines changed

2 files changed

+40
-17
lines changed

nginx.py

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
"""
88

99
import re
10+
import logging
1011

1112
INDENT = ' '
1213

14+
logging.basicConfig(level=logging.INFO)
1315

1416
class Error(Exception):
1517
pass
@@ -416,86 +418,98 @@ def loads(data, conf=True):
416418
index = 0
417419

418420
while True:
419-
m = re.compile(r'^\s*events\s*{', re.S).search(data[index:])
421+
m = re.compile(r'^\s*events\s*{').search(data[index:])
420422
if m:
423+
logging.debug("Open (Events)")
421424
e = Events()
422425
lopen.insert(0, e)
423426
index += m.end()
424427
continue
425428

426-
m = re.compile(r'^\s*http\s*{', re.S).search(data[index:])
429+
m = re.compile(r'^\s*http\s*{').search(data[index:])
427430
if m:
431+
logging.debug("Open (Http)")
428432
h = Http()
429433
lopen.insert(0, h)
430434
index += m.end()
431435
continue
432436

433-
m = re.compile(r'^\s*stream\s*{', re.S).search(data[index:])
437+
m = re.compile(r'^\s*stream\s*{').search(data[index:])
434438
if m:
439+
logging.debug("Open (Stream)")
435440
s = Stream()
436441
lopen.insert(0, s)
437442
index += m.end()
438443
continue
439444

440-
m = re.compile(r'^\s*server\s*{', re.S).search(data[index:])
445+
m = re.compile(r'^\s*server\s*{').search(data[index:])
441446
if m:
447+
logging.debug("Open (Server)")
442448
s = Server()
443449
lopen.insert(0, s)
444450
index += m.end()
445451
continue
446452

447453
n = re.compile(r'(?!\B"[^"]*);(?![^"]*"\B)')
448-
m = re.compile(r'^\s*location\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
454+
m = re.compile(r'^\s*location\s+(.*?".*?".*?|.*?)\s*{').search(data[index:])
449455
if m and not n.search(m.group()):
456+
logging.debug(f"Open (Location) {m.group(1)}")
450457
l = Location(m.group(1))
451458
lopen.insert(0, l)
452459
index += m.end()
453460
continue
454461

455-
m = re.compile(r'^\s*if\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
462+
m = re.compile(r'^\s*if\s+(.*?".*?".*?|.*?)\s*{').search(data[index:])
456463
if m and not n.search(m.group()):
464+
logging.debug(f"Open (If) {m.group(1)}")
457465
ifs = If(m.group(1))
458466
lopen.insert(0, ifs)
459467
index += m.end()
460468
continue
461469

462-
m = re.compile(r'^\s*upstream\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
470+
m = re.compile(r'^\s*upstream\s+(.*?)\s*{').search(data[index:])
463471
if m and not n.search(m.group()):
472+
logging.debug(f"Open (Upstream) {m.group(1)}")
464473
u = Upstream(m.group(1))
465474
lopen.insert(0, u)
466475
index += m.end()
467476
continue
468477

469-
m = re.compile(r'^\s*geo\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
478+
m = re.compile(r'^\s*geo\s+(.*?".*?".*?|.*?)\s*{').search(data[index:])
470479
if m and not n.search(m.group()):
480+
logging.debug(f"Open (Geo) {m.group(1)}")
471481
g = Geo(m.group(1))
472482
lopen.insert(0, g)
473483
index += m.end()
474484
continue
475485

476-
m = re.compile(r'^\s*map\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
486+
m = re.compile(r'^\s*map\s+(.*?".*?".*?|.*?)\s*{').search(data[index:])
477487
if m and not n.search(m.group()):
488+
logging.debug(f"Open (Map) {m.group(1)}")
478489
g = Map(m.group(1))
479490
lopen.insert(0, g)
480491
index += m.end()
481492
continue
482493

483-
m = re.compile(r'^\s*limit_except\s+(.*?)\s*(?!\B"[^"]*){(?![^"]*"\B)', re.S).search(data[index:])
494+
m = re.compile(r'^\s*limit_except\s+(.*?".*?".*?|.*?)\s*{').search(data[index:])
484495
if m and not n.search(m.group()):
496+
logging.debug(f"Open (LimitExcept) {m.group(1)}")
485497
l = LimitExcept(m.group(1))
486498
lopen.insert(0, l)
487499
index += m.end()
488500
continue
489501

490-
m = re.compile(r'^\s*types\s*{', re.S).search(data[index:])
502+
m = re.compile(r'^\s*types\s*{').search(data[index:])
491503
if m:
504+
logging.debug("Open (Types)")
492505
l = Types()
493506
lopen.insert(0, l)
494507
index += m.end()
495508
continue
496509

497-
m = re.compile(r'^(\s*)#[ \r\t\f]*(.*?)\n', re.S).search(data[index:])
510+
m = re.compile(r'^(\s*)#[ \r\t\f]*(.*?)\n').search(data[index:])
498511
if m:
512+
logging.debug(f"Comment ({m.group(2)})")
499513
c = Comment(m.group(2), inline='\n' not in m.group(1))
500514
if lopen and isinstance(lopen[0], Container):
501515
lopen[0].add(c)
@@ -504,9 +518,10 @@ def loads(data, conf=True):
504518
index += m.end() - 1
505519
continue
506520

507-
m = re.compile(r'^\s*}', re.S).search(data[index:])
521+
m = re.compile(r'^\s*}').search(data[index:])
508522
if m:
509523
if isinstance(lopen[0], Container):
524+
logging.debug(f"Close ({lopen[0].__class__.__name__})")
510525
c = lopen[0]
511526
lopen.pop(0)
512527
if lopen and isinstance(lopen[0], Container):
@@ -526,8 +541,9 @@ def loads(data, conf=True):
526541
normal = r'\s*[^;\s]*'
527542
s1 = r'{}|{}|{}'.format(double, single, normal)
528543
s = r'^\s*({})\s*((?:{})+);'.format(s1, s1)
529-
m = re.compile(s, re.S).search(data[index:])
544+
m = re.compile(s).search(data[index:])
530545
if m:
546+
logging.debug(f"Key {m.group(1)} {m.group(2)}")
531547
k = Key(m.group(1), m.group(2))
532548
if lopen and isinstance(lopen[0], (Container, Server)):
533549
lopen[0].add(k)
@@ -536,8 +552,9 @@ def loads(data, conf=True):
536552
index += m.end()
537553
continue
538554

539-
m = re.compile(r'^\s*(\S+);', re.S).search(data[index:])
555+
m = re.compile(r'^\s*(\S+);').search(data[index:])
540556
if m:
557+
logging.debug(f"Key {m.group(1)}")
541558
k = Key(m.group(1), '')
542559
if lopen and isinstance(lopen[0], (Container, Server)):
543560
lopen[0].add(k)

tests.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@
171171
if ( $http_user_agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" ) {
172172
return 403;
173173
}
174+
175+
location ~* ^/portal {
176+
proxy_set_header Connection "";
177+
rewrite ^/portal(.*) $1 break;
178+
}
174179
"""
175180

176181
TESTBLOCK_CASE_10 = """
@@ -314,15 +319,16 @@ def test_limit_expect(self):
314319
self.assertEqual(first_key.name, "deny")
315320
self.assertEqual(first_key.value, "all")
316321

317-
def test_semicolon_in_second_key_value(self):
322+
def test_key_value_quotes(self):
318323
inp_data = nginx.loads(TESTBLOCK_CASE_9)
319-
self.assertEqual(len(inp_data.filter("Location")), 1)
324+
self.assertEqual(len(inp_data.filter("Location")), 2)
320325
location_children = inp_data.filter("Location")[0].children
321326
self.assertEqual(len(location_children), 1)
322327
self.assertEqual(location_children[0].name, "add_header")
323328
self.assertEqual(location_children[0].value, 'X-XSS-Protection "1;mode-block"')
324329
self.assertEqual(len(inp_data.filter("If")), 1)
325330
self.assertEqual(inp_data.filter("If")[0].value, "( $http_user_agent = \"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)\" )")
331+
self.assertEqual(inp_data.filter("Location")[1].filter("Key", "proxy_set_header")[0].value, "Connection \"\"")
326332

327333
def test_types_block(self):
328334
inp_data = nginx.loads(TESTBLOCK_CASE_10)

0 commit comments

Comments
 (0)