From 5f5cfb7b0f8ca60be43dfb6c95b24b0967265945 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Wed, 13 Nov 2019 04:47:55 -0600 Subject: [PATCH] #254: quotes in annotations are not escaped Escapes the quotes for the annotations in the data file, and when converting an interval to JSON. The quotes in the annotations were already dequoted in IntervalFactory::fromSerialization, so we only needed to quote the strings when serializing or dumping to JSON. --- src/Interval.cpp | 4 ++-- test/annotate.t | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Interval.cpp b/src/Interval.cpp index 1d83c6cd..5d82566a 100644 --- a/src/Interval.cpp +++ b/src/Interval.cpp @@ -89,7 +89,7 @@ std::string Interval::serialize () const if (! annotation.empty ()) { out << (_tags.empty () ? " #" : "") - << " # \"" << annotation << "\""; + << " # \"" << escape (annotation, '"') << "\""; } return out.str (); @@ -138,7 +138,7 @@ std::string Interval::json () const out << ','; } - out << "\"annotation\":\"" << annotation << "\""; + out << "\"annotation\":\"" << escape (annotation, '"') << "\""; } out << "}"; diff --git a/test/annotate.t b/test/annotate.t index 9d97db07..e08cb6c8 100755 --- a/test/annotate.t +++ b/test/annotate.t @@ -178,6 +178,18 @@ class TestAnnotate(TestCase): self.assertEquals(len(j), 1) self.assertClosedInterval(j[0], expectedAnnotation="foo") + def test_annotate_with_embedded_quotes(self): + """Call 'annotate' with embedded quotes""" + now_utc = datetime.now().utcnow() + one_hour_before_utc = now_utc - timedelta(hours=1) + + self.t("track {:%Y-%m-%dT%H:%M:%S}Z - {:%Y-%m-%dT%H:%M:%S}Z".format(one_hour_before_utc, now_utc)) + self.t("annotate @1 'bar \"foo\" bar'") + + j = self.t.export() + + self.assertEquals(len(j), 1) + self.assertClosedInterval(j[0], expectedAnnotation='bar "foo" bar') if __name__ == "__main__": from simpletap import TAPTestRunner