Skip to content

Commit d336df5

Browse files
committed
Handle escaped double-quote in strings
1 parent ba46831 commit d336df5

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

src/bap/noeval_parser.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,23 @@ def _try_update_parent(parent, objs, stk):
9090

9191
def _parse_str(in_c, in_s, i, objs, stk):
9292
del in_c # unused
93-
endpos = in_s.find('"', i+1)
94-
if endpos < 0:
95-
raise ParserInputError("mismatched double-quote")
93+
endpos = i
94+
while True: # find non-escaped double quote
95+
endpos = in_s.find('"', endpos+1)
96+
if endpos < 0:
97+
raise ParserInputError("mismatched double-quote")
98+
if in_s[endpos-1] == '\\': # may be escaped double quote...
99+
# or could be a real quote after escaped slash
100+
# count slashes going back
101+
k = endpos - 2
102+
while k >= 0 and in_s[k] == '\\':
103+
k -= 1
104+
slashes = (endpos - 1) - k
105+
if slashes % 2 == 0: # this is really an ending double quote
106+
break
107+
# otherwise it's not
108+
continue
109+
break
96110
k = stk[-1]
97111
assert all((in_s[_k] in (' ', '\t', '\n') for _k in range(k, i))), \
98112
'pre quote is not whitespace at [%d..%d)' % (k, i)

tests/test_noeval_parser.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,32 @@ def hello(x):
7878
tok = lparser(s)
7979
assert tok == ("abc",)
8080

81+
def test_parser_9():
82+
# pylint: disable=missing-docstring,invalid-name
83+
s = r'"\""'
84+
tok = lparser(s)
85+
assert tok == '"'
86+
87+
def test_parser_10():
88+
# pylint: disable=missing-docstring,invalid-name
89+
s = '"\\\\"'
90+
assert eval(s) == '\\' # pylint: disable=eval-used
91+
tok = lparser(s)
92+
assert tok == '\\'
93+
94+
def test_parser_12():
95+
# pylint: disable=missing-docstring,invalid-name
96+
s = r'"\\\""'
97+
assert eval(s) == '\\"' # pylint: disable=eval-used
98+
tok = lparser(s)
99+
assert tok == '\\"'
100+
101+
def test_parser_11():
102+
# pylint: disable=missing-docstring,invalid-name
103+
s = r'"\'"'
104+
tok = lparser(s)
105+
assert tok == "'"
106+
81107
def test_parser_badinput_1():
82108
# pylint: disable=missing-docstring,invalid-name
83109
with pytest.raises(ParserInputError):

0 commit comments

Comments
 (0)