From 4c4d322becee806fe347f6ecda2f5750eb6aa64f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Mittelst=C3=A4dt?= <62167861+TheGalitube@users.noreply.github.com> Date: Fri, 30 Oct 2026 06:15:05 +0000 Subject: [PATCH] Reject multiple GPX document roots Found while testing crates/meta/src/gpx.rs:111 Co-Authored-By: GPT-6-Luna --- crates/meta/src/gpx.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/meta/src/gpx.rs b/crates/meta/src/gpx.rs index 204e39116..c59d41138 100644 --- a/crates/meta/src/gpx.rs +++ b/crates/meta/src/gpx.rs @@ -101,6 +101,7 @@ pub fn parse_gpx(s: &str) -> Result { reader.config_mut().check_end_names = true; let mut path: Vec> = Vec::new(); let mut seen_gpx = false; + let mut seen_root = false; let mut log = Tracklog::default(); let mut segment: u32 = 0; let mut pt: Option = None; @@ -111,6 +112,12 @@ pub fn parse_gpx(s: &str) -> Result { Event::Start(ref e) | Event::Empty(ref e) => { let name = local(e.name().as_ref()).to_vec(); let parent = path.last().map(Vec::as_slice); + if path.is_empty() { + if seen_root { + return Err(GpxError::Xml("multiple document elements".into())); + } + seen_root = true; + } match name.as_slice() { b"gpx" if path.is_empty() => seen_gpx = true, b"trk" if parent == Some(b"gpx") => log.tracks += 1, @@ -371,6 +378,11 @@ mod tests { assert!((g.longitude - -179.5).abs() < 1e-9, "{g:?}"); } + #[test] + fn rejects_multiple_document_roots() { + assert!(matches!(parse_gpx(""), Err(GpxError::Xml(_)))); + } + #[test] fn rejects_non_gpx_and_bad_input() { assert_eq!(parse_gpx(""), Err(GpxError::NotGpx));