aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
author Spartan322 <Megacake1234@gmail.com>2024-08-03 23:29:33 +0200
committer Spartan322 <Megacake1234@gmail.com>2024-08-03 23:29:33 +0200
commit2addc7763556ff76809f14e2063d1452aa9d6275 (patch)
tree996cac9cfa3c18798b5e509f51935a2538baac3f /src
parent2f6f6bdbb191aca01a1c4a9587e314442d219fb4 (diff)
Fix crash for empty/invalid/not-found filepaths
Add tests to validate empty string path Add tests to validate non-existent string path Add tests to validate nullptr buffer parser
Diffstat (limited to 'src')
-rw-r--r--src/openvic-dataloader/AbstractSyntaxTree.hpp3
-rw-r--r--src/openvic-dataloader/File.hpp9
-rw-r--r--src/openvic-dataloader/ParseState.hpp4
-rw-r--r--src/openvic-dataloader/csv/Parser.cpp7
-rw-r--r--src/openvic-dataloader/detail/ParseHandler.hpp56
-rw-r--r--src/openvic-dataloader/v2script/Parser.cpp7
6 files changed, 47 insertions, 39 deletions
diff --git a/src/openvic-dataloader/AbstractSyntaxTree.hpp b/src/openvic-dataloader/AbstractSyntaxTree.hpp
index f9f5796..f2d941b 100644
--- a/src/openvic-dataloader/AbstractSyntaxTree.hpp
+++ b/src/openvic-dataloader/AbstractSyntaxTree.hpp
@@ -23,6 +23,7 @@
namespace ovdl {
struct AbstractSyntaxTree : SymbolIntern {
+ AbstractSyntaxTree() = default;
explicit AbstractSyntaxTree(std::size_t max_elements) : _symbol_interner(max_elements) {}
symbol_type intern(const char* str, std::size_t length);
@@ -51,6 +52,8 @@ namespace ovdl {
using root_node_type = RootNodeT;
using node_type = typename file_type::node_type;
+ BasicAbstractSyntaxTree() = default;
+
explicit BasicAbstractSyntaxTree(file_type&& file)
: AbstractSyntaxTree(file.size() * file.visit_buffer([](auto&& buffer) -> size_t { return sizeof(typename std::decay_t<decltype(buffer)>::char_type); })),
_file { std::move(file) } {}
diff --git a/src/openvic-dataloader/File.hpp b/src/openvic-dataloader/File.hpp
index ec25640..cdab377 100644
--- a/src/openvic-dataloader/File.hpp
+++ b/src/openvic-dataloader/File.hpp
@@ -23,6 +23,7 @@ namespace ovdl {
lexy::buffer<lexy::utf32_encoding, void>,
lexy::buffer<lexy::byte_encoding, void>>;
+ File() = default;
explicit File(const char* path);
const char* path() const noexcept;
@@ -74,6 +75,7 @@ namespace ovdl {
decltype(auto) visit_buffer(Visitor&& visitor) {
switch (_buffer.index()) {
SWITCH_LIST
+ case 0: return visitor(lexy::buffer<> {});
default: ovdl::detail::unreachable();
}
}
@@ -82,6 +84,7 @@ namespace ovdl {
Return visit_buffer(Visitor&& visitor) {
switch (_buffer.index()) {
SWITCH_LIST
+ case 0: return visitor(lexy::buffer<> {});
default: ovdl::detail::unreachable();
}
}
@@ -90,6 +93,7 @@ namespace ovdl {
decltype(auto) visit_buffer(Visitor&& visitor) const {
switch (_buffer.index()) {
SWITCH_LIST
+ case 0: return visitor(lexy::buffer<> {});
default: ovdl::detail::unreachable();
}
}
@@ -98,6 +102,7 @@ namespace ovdl {
Return visit_buffer(Visitor&& visitor) const {
switch (_buffer.index()) {
SWITCH_LIST
+ case 0: return visitor(lexy::buffer<> {});
default: ovdl::detail::unreachable();
}
}
@@ -105,7 +110,7 @@ namespace ovdl {
#undef SWITCH_LIST
protected:
- const char* _path;
+ const char* _path = "";
std::size_t _buffer_size = 0;
detail::type_prepend_t<buffer_ids::variant_type, std::monostate> _buffer;
};
@@ -114,6 +119,8 @@ namespace ovdl {
struct BasicFile : File {
using node_type = NodeT;
+ BasicFile() = default;
+
template<typename Encoding, typename MemoryResource = void>
explicit BasicFile(const char* path, lexy::buffer<Encoding, MemoryResource>&& buffer)
: File(path) {
diff --git a/src/openvic-dataloader/ParseState.hpp b/src/openvic-dataloader/ParseState.hpp
index 806829c..259f2a5 100644
--- a/src/openvic-dataloader/ParseState.hpp
+++ b/src/openvic-dataloader/ParseState.hpp
@@ -30,6 +30,8 @@ namespace ovdl {
using file_type = typename ast_type::file_type;
using diagnostic_logger_type = BasicDiagnosticLogger<ParseState>;
+ ParseState() : _ast {}, _logger { this->ast().file() } {}
+
ParseState(typename ast_type::file_type&& file, detail::Encoding encoding)
: _ast { std::move(file) },
_logger { this->ast().file() },
@@ -69,6 +71,8 @@ namespace ovdl {
using file_type = FileT;
using diagnostic_logger_type = BasicDiagnosticLogger<FileParseState>;
+ FileParseState() : _file {}, _logger { this->file() } {}
+
FileParseState(file_type&& file, detail::Encoding encoding)
: _file { std::move(file) },
_logger { this->file() },
diff --git a/src/openvic-dataloader/csv/Parser.cpp b/src/openvic-dataloader/csv/Parser.cpp
index bbd1be4..e4416b2 100644
--- a/src/openvic-dataloader/csv/Parser.cpp
+++ b/src/openvic-dataloader/csv/Parser.cpp
@@ -57,9 +57,6 @@ struct Parser::ParseHandler final : detail::BasicFileParseHandler<CsvParseState>
}
Parser::error_range get_errors() {
- using iterator = typename decltype(std::declval<const error::Root*>()->children())::iterator;
- if (!is_valid())
- return dryad::make_node_range<error::Error>(iterator::from_ptr(nullptr), iterator::from_ptr(nullptr));
return parse_state().logger().get_errors();
}
@@ -129,7 +126,7 @@ constexpr void Parser::_run_load_func(detail::LoadCallback<ParseHandler, Args...
if (!error_message.empty()) {
_has_error = true;
_has_fatal_error = true;
- _parse_handler->parse_state().logger().template create_log<error::BufferError>(DiagnosticLogger::DiagnosticKind::error, fmt::runtime(error_message));
+ _parse_handler->parse_state().logger().template create_log<error::BufferError>(DiagnosticLogger::DiagnosticKind::error, fmt::runtime(error_message), _file_path);
}
if (has_error() && &_error_stream.get() != &detail::cnull) {
print_errors_to(_error_stream.get());
@@ -235,7 +232,7 @@ void Parser::print_errors_to(std::basic_ostream<char>& stream) const {
dryad::visit_tree(
error,
[&](const error::BufferError* buffer_error) {
- stream << "buffer error: " << this->error(buffer_error) << '\n';
+ stream << this->error(buffer_error) << '\n';
},
[&](dryad::child_visitor<error::ErrorKind> visitor, const error::AnnotatedError* annotated_error) {
stream << this->error(annotated_error) << '\n';
diff --git a/src/openvic-dataloader/detail/ParseHandler.hpp b/src/openvic-dataloader/detail/ParseHandler.hpp
index 9666a5b..28222ae 100644
--- a/src/openvic-dataloader/detail/ParseHandler.hpp
+++ b/src/openvic-dataloader/detail/ParseHandler.hpp
@@ -26,11 +26,11 @@ namespace ovdl::detail {
case buffer_is_null:
return "Buffer could not be loaded.";
case os_error:
- return "OS file error.";
+ return "OS file error for '{}'.";
case file_not_found:
- return "File not found.";
+ return "File '{}' not found.";
case permission_denied:
- return "Read Permission denied.";
+ return "Read Permission for '{}' denied.";
default:
return "";
}
@@ -78,19 +78,20 @@ namespace ovdl::detail {
virtual const char* path_impl() const = 0;
template<detail::IsStateType State, detail::IsEncoding BufferEncoding>
- static constexpr auto generate_state = [](std::optional<State>* state, const char* path, auto&& buffer, Encoding encoding) {
+ static constexpr auto generate_state = [](State* state, const char* path, auto&& buffer, Encoding encoding) {
if (path[0] != '\0') {
- state->emplace(
+ *state = {
path,
lexy::buffer<BufferEncoding>(std::move(buffer)),
- encoding);
+ encoding
+ };
return;
}
- state->emplace(lexy::buffer<BufferEncoding>(std::move(buffer)), encoding);
+ *state = { lexy::buffer<BufferEncoding>(std::move(buffer)), encoding };
};
template<detail::IsStateType State>
- static void create_state(std::optional<State>* state, const char* path, lexy::buffer<lexy::default_encoding>&& buffer, std::optional<Encoding> fallback) {
+ static void create_state(State* state, const char* path, lexy::buffer<lexy::default_encoding>&& buffer, std::optional<Encoding> fallback) {
if (!_system_fallback_encoding.has_value()) {
_detect_system_fallback_encoding();
}
@@ -121,15 +122,15 @@ namespace ovdl::detail {
}
if (!is_alone) {
- (*state)->logger().info("encoding type could not be distinguished");
+ state->logger().info("encoding type could not be distinguished");
}
if (is_bad_fallback) {
- (*state)->logger().warning("fallback encoding cannot be ascii or utf8");
+ state->logger().warning("fallback encoding cannot be ascii or utf8");
}
if (encoding == ovdl::detail::Encoding::Unknown) {
- (*state)->logger().warning("could not detect encoding");
+ state->logger().warning("could not detect encoding");
}
}
@@ -143,36 +144,37 @@ namespace ovdl::detail {
using parse_state_type = ParseState;
virtual constexpr bool is_valid_impl() const {
- if (!_parse_state) return false;
- return _parse_state.value().file().is_valid();
+ return _parse_state.file().is_valid();
}
constexpr virtual buffer_error load_buffer_impl(lexy::buffer<lexy::default_encoding>&& buffer, const char* path, std::optional<Encoding> fallback) {
- if (buffer.data() == nullptr) return buffer_error::buffer_is_null;
+ if (buffer.data() == nullptr) {
+ _parse_state = {};
+ return buffer_error::buffer_is_null;
+ }
create_state(&_parse_state, path, std::move(buffer), fallback);
return is_valid_impl() ? buffer_error::success : buffer_error::buffer_is_null;
}
virtual const char* path_impl() const {
- if (!_parse_state) return "";
- return _parse_state.value().file().path();
+ return _parse_state.file().path();
}
parse_state_type& parse_state() {
- return _parse_state.value();
+ return _parse_state;
}
const parse_state_type& parse_state() const {
- return _parse_state.value();
+ return _parse_state;
}
template<typename Encoding>
constexpr const auto& buffer() const {
- return _parse_state.value().file().template get_buffer_as<Encoding>();
+ return _parse_state.file().template get_buffer_as<Encoding>();
}
protected:
- std::optional<parse_state_type> _parse_state;
+ parse_state_type _parse_state;
};
template<detail::IsParseState ParseState>
@@ -180,8 +182,7 @@ namespace ovdl::detail {
using parse_state_type = ParseState;
virtual constexpr bool is_valid_impl() const {
- if (!_parse_state) return false;
- return _parse_state.value().ast().file().is_valid();
+ return _parse_state.ast().file().is_valid();
}
constexpr virtual buffer_error load_buffer_impl(lexy::buffer<lexy::default_encoding>&& buffer, const char* path, std::optional<Encoding> fallback) {
@@ -191,24 +192,23 @@ namespace ovdl::detail {
}
virtual const char* path_impl() const {
- if (!_parse_state) return "";
- return _parse_state.value().ast().file().path();
+ return _parse_state.ast().file().path();
}
parse_state_type& parse_state() {
- return _parse_state.value();
+ return _parse_state;
}
const parse_state_type& parse_state() const {
- return _parse_state.value();
+ return _parse_state;
}
template<typename Encoding>
constexpr const auto& buffer() const {
- return _parse_state.value().ast().file().template get_buffer_as<Encoding>();
+ return _parse_state.ast().file().template get_buffer_as<Encoding>();
}
protected:
- std::optional<parse_state_type> _parse_state;
+ parse_state_type _parse_state;
};
} \ No newline at end of file
diff --git a/src/openvic-dataloader/v2script/Parser.cpp b/src/openvic-dataloader/v2script/Parser.cpp
index e5234d6..9b36a95 100644
--- a/src/openvic-dataloader/v2script/Parser.cpp
+++ b/src/openvic-dataloader/v2script/Parser.cpp
@@ -77,9 +77,6 @@ struct Parser::ParseHandler final : detail::BasicStateParseHandler<v2script::ast
}
Parser::error_range get_errors() {
- using iterator = typename decltype(std::declval<const error::Root*>()->children())::iterator;
- if (!is_valid())
- return dryad::make_node_range<error::Error>(iterator::from_ptr(nullptr), iterator::from_ptr(nullptr));
return parse_state().logger().get_errors();
}
};
@@ -146,7 +143,7 @@ constexpr void Parser::_run_load_func(detail::LoadCallback<Parser::ParseHandler*
if (!error_message.empty()) {
_has_error = true;
_has_fatal_error = true;
- _parse_handler->parse_state().logger().template create_log<error::BufferError>(DiagnosticLogger::DiagnosticKind::error, fmt::runtime(error_message));
+ _parse_handler->parse_state().logger().template create_log<error::BufferError>(DiagnosticLogger::DiagnosticKind::error, fmt::runtime(error_message), _file_path);
}
if (has_error() && &_error_stream.get() != &detail::cnull) {
print_errors_to(_error_stream.get());
@@ -356,7 +353,7 @@ void Parser::print_errors_to(std::basic_ostream<char>& stream) const {
dryad::visit_tree(
error,
[&](const error::BufferError* buffer_error) {
- stream << "buffer error: " << this->error(buffer_error) << '\n';
+ stream << this->error(buffer_error) << '\n';
},
[&](dryad::child_visitor<error::ErrorKind> visitor, const error::AnnotatedError* annotated_error) {
stream << this->error(annotated_error) << '\n';