From c1f3d8be72e2f175477ba44c3e7c755e8bfa2ed0 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Tue, 3 Mar 2020 20:32:41 -0600 Subject: [PATCH] Check serialization before writing to database Ensure that the IntervalFactory can parse the string returned by Interval::serialize before writing to database. If a user attempts to add a non-parseable date, you will get an error like: $ TZ="GMT" timew track 7h before 1970-01-01T00:00:00 test Note: 'test' is a new tag. Internal error. Failed encode / decode check. Or if the user attempts to add a tag that is not supported: $ timew start 1970-01-01T00:00:00 '\"TEST\"' Note: '"\\"TEST\\""' is a new tag. Internal error. Failed encode / decode check. On #159, the serializer / deserializer should be able to handle the escaped quotes, but it is another example where we do not want any entry written into the database that cannot be properly parsed. This change will also add more verbose debugging information if the :debug flag is passed, like: $ timew start 1970-01-01T00:00:00 '\"TEST\"' :debug CLI Parser _original_args timew start 1970-01-01T00:00:00 \"TEST\" :debug _args word basename='timew' raw='timew' BINARY word canonical='start' raw='start' ORIGINAL CMD date raw='1970-01-01T00:00:00' ORIGINAL FILTER word raw='\"TEST\"' ORIGINAL FILTER TAG word canonical=':debug' raw=':debug' ORIGINAL HINT FILTER >> 2020-02.data: 0 intervals >> 1970-01.data: 0 intervals >> 1969-12.data: 0 intervals >> Loaded 0 tracked intervals Note: '"\\"TEST\\""' is a new tag. >> Datafile::addInterval() failed. >> Encode / decode check failed: >> inc 19700101T060000Z # "\\"TEST\\"" >> is not equal to: >> inc 19700101T060000Z # "TEST\\\"\"" \ Internal error. Failed encode / decode check. >> Timer timew 0.002137 sec Closes #290 Related to #159 Signed-off-by: Shaun Ruffell --- src/Datafile.cpp | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Datafile.cpp b/src/Datafile.cpp index c504cc48..9f381cb5 100644 --- a/src/Datafile.cpp +++ b/src/Datafile.cpp @@ -33,6 +33,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////////////////// void Datafile::initialize (const std::string& name) @@ -96,13 +97,29 @@ void Datafile::addInterval (const Interval& interval) if (! _lines_loaded) load_lines (); - // TODO if interval is not a duplicate - // TODO insert interval.serialize into _lines - // TODO _dirty = true; + const std::string serialization = interval.serialize (); - _lines.push_back (interval.serialize ()); - debug (format ("{1}: Added {2}", _file.name (), _lines.back ())); - _dirty = true; + // Ensure that the IntervalFactory can properly parse the serialization before + // adding it to the database. + try + { + Interval test = IntervalFactory::fromSerialization (serialization); + test.id = interval.id; + if (interval != test) + { + throw (format ("Encode / decode check failed:\n {1}\nis not equal to:\n {2}", + serialization, test.serialize ())); + } + + _lines.push_back (serialization); + debug (format ("{1}: Added {2}", _file.name (), _lines.back ())); + _dirty = true; + } + catch (const std::string& error) + { + debug (format ("Datafile::addInterval() failed.\n{1}", error)); + throw std::string ("Internal error. Failed encode / decode check."); + } } ////////////////////////////////////////////////////////////////////////////////