Skip to content

Commit 762d369

Browse files
authored
Merge pull request #1103 from jasonccox/main
Require matching BEGIN and END lines in vobjects
2 parents 2396c46 + 7a387b8 commit 762d369

File tree

4 files changed

+38
-0
lines changed

4 files changed

+38
-0
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ In alphabetical order:
99
- Corey Hinshaw
1010
- Kai Herlemann
1111
- Hugo Osvaldo Barrera
12+
- Jason Cox
1213
- Julian Mehne
1314
- Malte Kiefer
1415
- Marek Marczykowski-Górecki

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Version 0.19.3
1515
- Added a no_delete option to the storage configuration. :gh:`1090`
1616
- Fix crash when running ``vdirsyncer repair`` on a collection. :gh:`1019`
1717
- Add an option to request vCard v4.0. :gh:`1066`
18+
- Require matching ``BEGIN`` and ``END`` lines in vobjects. :gh:`1103`
1819

1920
Version 0.19.2
2021
==============

tests/unit/utils/test_vobject.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,31 @@ def test_broken_item():
237237
assert item.parsed is None
238238

239239

240+
def test_mismatched_end():
241+
with pytest.raises(ValueError) as excinfo:
242+
vobject._Component.parse(
243+
[
244+
"BEGIN:FOO",
245+
"END:BAR",
246+
]
247+
)
248+
249+
assert "Got END:BAR, expected END:FOO at line 2" in str(excinfo.value)
250+
251+
252+
def test_missing_end():
253+
with pytest.raises(ValueError) as excinfo:
254+
vobject._Component.parse(
255+
[
256+
"BEGIN:FOO",
257+
"BEGIN:BAR",
258+
"END:BAR",
259+
]
260+
)
261+
262+
assert "Missing END for component(s): FOO" in str(excinfo.value)
263+
264+
240265
def test_multiple_items():
241266
with pytest.raises(ValueError) as excinfo:
242267
vobject._Component.parse(

vdirsyncer/vobject.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,12 @@ def parse(cls, lines, multiple=False):
281281
stack.append(cls(c_name, [], []))
282282
elif line.startswith("END:"):
283283
component = stack.pop()
284+
c_name = line[len("END:") :].strip().upper()
285+
if c_name != component.name:
286+
raise ValueError(
287+
f"Got END:{c_name}, expected END:{component.name}"
288+
+ f" at line {_i + 1}"
289+
)
284290
if stack:
285291
stack[-1].subcomponents.append(component)
286292
else:
@@ -291,6 +297,11 @@ def parse(cls, lines, multiple=False):
291297
except IndexError:
292298
raise ValueError(f"Parsing error at line {_i + 1}")
293299

300+
if len(stack) > 0:
301+
raise ValueError(
302+
f"Missing END for component(s): {', '.join(c.name for c in stack)}"
303+
)
304+
294305
if multiple:
295306
return rv
296307
elif len(rv) != 1:

0 commit comments

Comments
 (0)