Skip to content

Commit 921ec4d

Browse files
committed
All kinds of bugs found in issue #41
1 parent d30ca36 commit 921ec4d

File tree

3 files changed

+126
-15
lines changed

3 files changed

+126
-15
lines changed

src/NetTopologySuite.IO.GPX/GpxReader.cs

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -132,27 +132,19 @@ public static void Read(XmlReader reader, GpxReaderSettings settings, GpxVisitor
132132
break;
133133
}
134134

135-
bool expectingMetadata = true;
135+
bool foundMetadata = false;
136136
bool expectingExtensions = true;
137137
do
138138
{
139-
if (expectingMetadata)
140-
{
141-
expectingMetadata = false;
142-
if (reader.Name == "metadata")
143-
{
144-
ReadMetadata(reader, settings, creator, visitor);
145-
}
146-
else
147-
{
148-
visitor.VisitMetadata(new GpxMetadata(creator));
149-
}
150-
}
151-
152139
switch (reader.Name)
153140
{
154141
// ideally, it should all be in this order, since the XSD validation
155142
// would fail otherwise, but whatever.
143+
case "metadata":
144+
ReadMetadata(reader, settings, creator, visitor);
145+
foundMetadata = true;
146+
break;
147+
156148
case "wpt":
157149
ReadWaypoint(reader, settings, visitor);
158150
break;
@@ -174,10 +166,28 @@ public static void Read(XmlReader reader, GpxReaderSettings settings, GpxVisitor
174166
visitor.VisitExtensions(extensions);
175167
}
176168

169+
break;
170+
case "":
171+
case "gpx":
172+
break;
173+
default:
174+
if (settings.IgnoreBadElements)
175+
{
176+
ReadTo(reader, XmlNodeType.EndElement, XmlNodeType.EndElement);
177+
}
178+
else
179+
{
180+
throw new XmlException($"Invalid xml node '{reader.Name}'");
181+
}
177182
break;
178183
}
179184
}
180185
while (ReadTo(reader, XmlNodeType.Element, XmlNodeType.EndElement));
186+
187+
if (!foundMetadata)
188+
{
189+
visitor.VisitMetadata(new GpxMetadata(creator));
190+
}
181191
}
182192
}
183193

src/NetTopologySuite.IO.GPX/GpxReaderSettings.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,12 @@ public TimeZoneInfo TimeZoneInfo
6565
/// breaking change.
6666
/// </summary>
6767
public bool BuildWebLinksForVeryLongUriValues { get; set; }
68+
69+
/// <summary>
70+
/// Gets or sets a value indicating whether or not to ignore files with elements not part of the contract
71+
/// even though such files would not pass XSD validation (see
72+
/// NetTopologySuite/NetTopologySuite.IO.GPX#29).
73+
/// </summary>
74+
public bool IgnoreBadElements { get; set; }
6875
}
6976
}

tests/NetTopologySuite.IO.GPX.Tests/GpxFileTests.cs

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ public void TimestampsShouldPreserveFractionalSecondsWithinDefinedPrecision()
344344
</wpt>
345345
</gpx>
346346
";
347-
string text = GpxFile.Parse(GpxText, null). BuildString(null);
347+
string text = GpxFile.Parse(GpxText, null).BuildString(null);
348348

349349
Assert.Contains("1234-05-06T07:08:09.7654321Z", text);
350350
Assert.Contains("5432-10-10T11:22:33.8765432Z", text); // DateTime resolution is 100ns, so the value gets rounded to 7 digits
@@ -502,5 +502,99 @@ public void OverlongDataUrisShouldBeAccepted_OptIn(int totalUriLength)
502502
string text = file.BuildString(null);
503503
Assert.Contains(uriText, text);
504504
}
505+
506+
[Fact]
507+
[GitHubIssue(41)]
508+
public void BadFileWithIncorrectXmlNode_ShouldThrow()
509+
{
510+
string gpxText = $@"
511+
<gpx version='1.1' creator='S Health_0.2' n0:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd' xmlns='http://www.topografix.com/GPX/1/1' n1:xsi='http://www.w3.org/2001/XMLSchema-instance' n1:gpx1='http://www.topografix.com/GPX/1/0' n1:ogt10='http://gpstracker.android.sogeti.n1/GPX/1/0' xmlns:n0='xsi' xmlns:n1='xmlns'>
512+
<metadate>2020-07-31T03:01:31Z</metadate>
513+
<trk>
514+
<name>20200731_090010.gpx</name>
515+
<trkseg>
516+
<trkpt lat='32.737328' lon='35.65718'>
517+
<ele>346.0538</ele>
518+
<time>2020-07-31T03:01:31Z</time>
519+
</trkpt>
520+
</trkseg>
521+
</trk>
522+
<exerciseinfo>
523+
<exercisetype>11007</exercisetype>
524+
</exerciseinfo>
525+
</gpx>
526+
";
527+
Assert.ThrowsAny<XmlException>(() => GpxFile.Parse(gpxText, null));
528+
}
529+
530+
[Fact]
531+
[GitHubIssue(41)]
532+
public void BadFileWithIncorrectXmlNode_Ignored_ShouldNotThrow()
533+
{
534+
string gpxText = $@"
535+
<gpx version='1.1' creator='S Health_0.2' n0:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd' xmlns='http://www.topografix.com/GPX/1/1' n1:xsi='http://www.w3.org/2001/XMLSchema-instance' n1:gpx1='http://www.topografix.com/GPX/1/0' n1:ogt10='http://gpstracker.android.sogeti.n1/GPX/1/0' xmlns:n0='xsi' xmlns:n1='xmlns'>
536+
<trk>
537+
<name>20200731_090010.gpx</name>
538+
<trkseg>
539+
<trkpt lat='32.737328' lon='35.65718'>
540+
<ele>346.0538</ele>
541+
<time>2020-07-31T03:01:31Z</time>
542+
</trkpt>
543+
</trkseg>
544+
</trk>
545+
<exerciseinfo>
546+
<exercisetype>11007</exercisetype>
547+
</exerciseinfo>
548+
</gpx>
549+
";
550+
var gpx = GpxFile.Parse(gpxText, new GpxReaderSettings { IgnoreBadElements = true });
551+
Assert.NotNull(gpx);
552+
}
553+
554+
[Fact]
555+
[GitHubIssue(41)]
556+
public void BadFileWithMetadate_Ignored_ShouldNotThrow()
557+
{
558+
string gpxText = $@"
559+
<gpx version='1.1' creator='S Health_0.2' n0:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd' xmlns='http://www.topografix.com/GPX/1/1' n1:xsi='http://www.w3.org/2001/XMLSchema-instance' n1:gpx1='http://www.topografix.com/GPX/1/0' n1:ogt10='http://gpstracker.android.sogeti.n1/GPX/1/0' xmlns:n0='xsi' xmlns:n1='xmlns'>
560+
<metadate>2020-07-31T03:01:31Z</metadate>
561+
<trk>
562+
<name>20200731_090010.gpx</name>
563+
<trkseg>
564+
<trkpt lat='32.737328' lon='35.65718'>
565+
<ele>346.0538</ele>
566+
<time>2020-07-31T03:01:31Z</time>
567+
</trkpt>
568+
</trkseg>
569+
</trk>
570+
</gpx>
571+
";
572+
var gpx = GpxFile.Parse(gpxText, new GpxReaderSettings { IgnoreBadElements = true });
573+
Assert.NotNull(gpx);
574+
}
575+
576+
[Fact]
577+
[GitHubIssue(41)]
578+
public void MetadataIsNotFirst_ShouldNotHang()
579+
{
580+
string gpxText = $@"
581+
<gpx version='1.1' creator='HarelM' n0:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd' xmlns='http://www.topografix.com/GPX/1/1' n1:xsi='http://www.w3.org/2001/XMLSchema-instance' n1:gpx1='http://www.topografix.com/GPX/1/0' n1:ogt10='http://gpstracker.android.sogeti.n1/GPX/1/0' xmlns:n0='xsi' xmlns:n1='xmlns'>
582+
<trk>
583+
<name>20200731_090010.gpx</name>
584+
<trkseg>
585+
<trkpt lat='32.737328' lon='35.65718'>
586+
<ele>346.0538</ele>
587+
<time>2020-07-31T03:01:31Z</time>
588+
</trkpt>
589+
</trkseg>
590+
</trk>
591+
<metadata>
592+
<link href='somelink.com' />
593+
</metadata>
594+
</gpx>
595+
";
596+
var gpx = GpxFile.Parse(gpxText, null);
597+
Assert.Single(gpx.Metadata.Links.ToArray());
598+
}
505599
}
506600
}

0 commit comments

Comments
 (0)