Skip to content

Commit 90686b7

Browse files
committed
Detect incorrectly delimited strings
Strings should be delimited on both ends by double quotes, but this is currently not being been detected, and content is simply being incorrectly trimmed. This commit adds a check for each string to verify it starts and ends with a double quote character, issuing a warning/error if that's not the case (and fixing it as appropriate). A few new test cases have been added to check that the lack of double quotes to delimit strings issues errors as expected. Signed-off-by: Rodrigo Tobar <[email protected]>
1 parent 10b8023 commit 90686b7

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

babel/messages/pofile.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,17 @@ def _process_keyword_line(self, lineno, line, obsolete=False) -> None:
278278

279279
self.obsolete = obsolete
280280

281+
def _normalized_string(s):
282+
# whole lines are already stripped on both ends
283+
s = s.lstrip()
284+
if s[0] != '"':
285+
self._invalid_pofile(line, lineno, "String must be delimited on the left by double quotes")
286+
s = '"' + s
287+
if s[-1] != '"':
288+
self._invalid_pofile(line, lineno, "String must be delimited on the left by double quotes")
289+
s += '"'
290+
return _NormalizedString(s)
291+
281292
# The line that has the msgid is stored as the offset of the msg
282293
# should this be the msgctxt if it has one?
283294
if keyword == 'msgid':
@@ -286,20 +297,20 @@ def _process_keyword_line(self, lineno, line, obsolete=False) -> None:
286297
if keyword in ['msgid', 'msgid_plural']:
287298
self.in_msgctxt = False
288299
self.in_msgid = True
289-
self.messages.append(_NormalizedString(arg))
300+
self.messages.append(_normalized_string(arg))
290301

291302
elif keyword == 'msgstr':
292303
self.in_msgid = False
293304
self.in_msgstr = True
294305
if arg.startswith('['):
295306
idx, msg = arg[1:].split(']', 1)
296-
self.translations.append([int(idx), _NormalizedString(msg)])
307+
self.translations.append([int(idx), _normalized_string(msg)])
297308
else:
298-
self.translations.append([0, _NormalizedString(arg)])
309+
self.translations.append([0, _normalized_string(arg)])
299310

300311
elif keyword == 'msgctxt':
301312
self.in_msgctxt = True
302-
self.context = _NormalizedString(arg)
313+
self.context = _normalized_string(arg)
303314

304315
def _process_string_continuation_line(self, line, lineno) -> None:
305316
if self.in_msgid:
@@ -311,6 +322,10 @@ def _process_string_continuation_line(self, line, lineno) -> None:
311322
else:
312323
self._invalid_pofile(line, lineno, "Got line starting with \" but not in msgid, msgstr or msgctxt")
313324
return
325+
assert line[0] == '"'
326+
if line[-1] != '"':
327+
self._invalid_pofile(line, lineno, "String must be delimited by double quotes")
328+
line += '"'
314329
s.append(line)
315330

316331
def _process_comment(self, line) -> None:

tests/messages/test_pofile.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,22 @@ def test_abort_invalid_po_file(self):
529529
Pour toute question, veuillez communiquer avec Fulano a [email protected]
530530
"
531531
'''
532+
invalid_po_3 = '''
533+
msgid *A"
534+
msgstr "B"
535+
'''
536+
537+
invalid_po_4 = '''
538+
msgid "A"
539+
msgstr "B*
540+
'''
541+
542+
invalid_po_5 = '''
543+
msgid "A"
544+
msgstr ""
545+
"*
546+
'''
547+
532548
# Catalog not created, throws Unicode Error
533549
buf = StringIO(invalid_po)
534550
output = pofile.read_po(buf, locale='fr', abort_invalid=False)
@@ -544,6 +560,12 @@ def test_abort_invalid_po_file(self):
544560
output = pofile.read_po(buf, locale='fr', abort_invalid=False)
545561
assert isinstance(output, Catalog)
546562

563+
# Catalog not created, aborted with PoFileError
564+
for incorrectly_delimited_po_string in (invalid_po_3, invalid_po_4, invalid_po_5):
565+
buf = StringIO(incorrectly_delimited_po_string)
566+
with pytest.raises(pofile.PoFileError):
567+
pofile.read_po(buf, locale='es', abort_invalid=True)
568+
547569
def test_invalid_pofile_with_abort_flag(self):
548570
parser = pofile.PoFileParser(None, abort_invalid=True)
549571
lineno = 10

0 commit comments

Comments
 (0)