Skip to content

Commit 1c14ff2

Browse files
lpyu001miss-islington
authored andcommitted
gh-155468: Distinguish empty quoted tokens from EOF in netrc (GH-155471)
(cherry picked from commit 2a37d67) Co-authored-by: stevens <lipengyu@kylinos.cn>
1 parent f6b7e5b commit 1c14ff2

3 files changed

Lines changed: 26 additions & 8 deletions

File tree

Lib/netrc.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,12 @@ def _read_char(self):
4848
def get_token(self):
4949
if self.pushback:
5050
return self.pushback.pop(0)
51-
token = ""
51+
token = None
5252
fiter = iter(self._read_char, "")
5353
for ch in fiter:
5454
if ch in self.whitespace:
5555
continue
56+
token = ""
5657
if ch == '"':
5758
for ch in fiter:
5859
if ch == '"':
@@ -96,9 +97,9 @@ def _parse(self, file, fp, default_netrc):
9697
# Look for a machine, default, or macdef top-level keyword
9798
saved_lineno = lexer.lineno
9899
tt = lexer.get_token()
99-
if not tt:
100+
if tt is None:
100101
break
101-
elif tt[0] == '#':
102+
elif tt.startswith('#'):
102103
if lexer.lineno == saved_lineno and len(tt) == 1:
103104
lexer.instream.readline()
104105
continue
@@ -135,20 +136,20 @@ def _parse(self, file, fp, default_netrc):
135136
while 1:
136137
prev_lineno = lexer.lineno
137138
tt = lexer.get_token()
138-
if tt.startswith('#'):
139+
if tt is not None and tt.startswith('#'):
139140
if lexer.lineno == prev_lineno:
140141
lexer.instream.readline()
141142
continue
142-
if tt in {'', 'machine', 'default', 'macdef'}:
143+
if tt in {None, 'machine', 'default', 'macdef'}:
143144
self.hosts[entryname] = (login, account, password)
144145
lexer.push_token(tt)
145146
break
146147
elif tt == 'login' or tt == 'user':
147-
login = lexer.get_token()
148+
login = lexer.get_token() or ''
148149
elif tt == 'account':
149-
account = lexer.get_token()
150+
account = lexer.get_token() or ''
150151
elif tt == 'password':
151-
password = lexer.get_token()
152+
password = lexer.get_token() or ''
152153
else:
153154
raise NetrcParseError("bad follower token %r" % tt,
154155
file, lexer.lineno)

Lib/test/test_netrc.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ def test_optional_tokens(self):
6262
"machine host.domain.com login",
6363
"machine host.domain.com account",
6464
"machine host.domain.com password",
65+
"machine host.domain.com login \"\"",
66+
"machine host.domain.com account \"\"",
67+
"machine host.domain.com password \"\"",
6568
"machine host.domain.com login \"\" account",
6669
"machine host.domain.com login \"\" password",
6770
"machine host.domain.com account \"\" password"
@@ -74,6 +77,9 @@ def test_optional_tokens(self):
7477
"default login",
7578
"default account",
7679
"default password",
80+
"default login \"\"",
81+
"default account \"\"",
82+
"default password \"\"",
7783
"default login \"\" account",
7884
"default login \"\" password",
7985
"default account \"\" password"
@@ -82,6 +88,15 @@ def test_optional_tokens(self):
8288
nrc = self.make_nrc(item)
8389
self.assertEqual(nrc.hosts['default'], ('', '', ''))
8490

91+
def test_empty_quoted_token_is_not_eof(self):
92+
data = (
93+
'"" invalid',
94+
'machine host.domain.com "" invalid',
95+
)
96+
for item in data:
97+
with self.subTest(item=item):
98+
self.assertRaises(netrc.NetrcParseError, self.make_nrc, item)
99+
85100
def test_invalid_tokens(self):
86101
data = (
87102
"invalid host.domain.com",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :mod:`netrc` to distinguish empty quoted tokens from end-of-file, so
2+
malformed files no longer cause the remaining content to be silently ignored.

0 commit comments

Comments
 (0)