summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2021-01-19 20:28:40 +0100
committerRoman Smrž <roman.smrz@seznam.cz>2021-01-19 21:44:22 +0100
commitb60e7b5e07033b926c29042ba6b267d5af32f7e3 (patch)
tree864ea0623e5111058ddfe586e280469009909065
parentec8ec7eb2a0b677f80f89834d955d1f0aa614538 (diff)
Storage: handle parsing errors without throwing exceptions
-rw-r--r--src/storage.cpp26
1 files changed, 21 insertions, 5 deletions
diff --git a/src/storage.cpp b/src/storage.cpp
index 4f48c67..51ce9bc 100644
--- a/src/storage.cpp
+++ b/src/storage.cpp
@@ -24,12 +24,14 @@ using std::copy;
using std::get;
using std::holds_alternative;
using std::ifstream;
+using std::invalid_argument;
using std::is_same_v;
using std::make_shared;
using std::make_unique;
using std::monostate;
using std::nullopt;
using std::ofstream;
+using std::out_of_range;
using std::runtime_error;
using std::scoped_lock;
using std::shared_ptr;
@@ -980,12 +982,12 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st,
while (begin != end) {
const auto colon = std::find(begin, end, ':');
if (colon == end)
- throw runtime_error("invalid record");
+ return nullopt;
const string name(begin, colon);
const auto space = std::find(colon + 1, end, ' ');
if (space == end)
- throw runtime_error("invalid record");
+ return nullopt;
const string type(colon + 1, space);
begin = space + 1;
@@ -993,7 +995,7 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st,
for (bool cont = true; cont; ) {
auto newline = std::find(begin, end, '\n');
if (newline == end)
- throw runtime_error("invalid record");
+ return nullopt;
if (newline + 1 != end && *(newline + 1) == '\t')
newline++;
@@ -1005,7 +1007,13 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st,
}
if (type == "i")
- items->emplace_back(name, std::stoi(value));
+ try {
+ items->emplace_back(name, std::stoi(value));
+ } catch (invalid_argument &) {
+ return nullopt;
+ } catch (out_of_range &) {
+ return nullopt; // TODO
+ }
else if (type == "t")
items->emplace_back(name, value);
else if (type == "b")
@@ -1163,7 +1171,15 @@ ObjectT<S>::decodePrefix(const S & st,
if (space == newline)
return nullopt;
- ssize_t size = std::stoi(string(space + 1, newline));
+ ssize_t size;
+ try {
+ size = std::stol(string(space + 1, newline));
+ } catch (invalid_argument &) {
+ return nullopt;
+ } catch (out_of_range &) {
+ // Way too big to handle anyway
+ return nullopt;
+ }
if (end - newline - 1 < size)
return nullopt;
auto cend = newline + 1 + size;