diff options
author | Spartan322 <Megacake1234@gmail.com> | 2024-08-03 23:29:33 +0200 |
---|---|---|
committer | Spartan322 <Megacake1234@gmail.com> | 2024-08-03 23:29:33 +0200 |
commit | 2addc7763556ff76809f14e2063d1452aa9d6275 (patch) | |
tree | 996cac9cfa3c18798b5e509f51935a2538baac3f /src | |
parent | 2f6f6bdbb191aca01a1c4a9587e314442d219fb4 (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.hpp | 3 | ||||
-rw-r--r-- | src/openvic-dataloader/File.hpp | 9 | ||||
-rw-r--r-- | src/openvic-dataloader/ParseState.hpp | 4 | ||||
-rw-r--r-- | src/openvic-dataloader/csv/Parser.cpp | 7 | ||||
-rw-r--r-- | src/openvic-dataloader/detail/ParseHandler.hpp | 56 | ||||
-rw-r--r-- | src/openvic-dataloader/v2script/Parser.cpp | 7 |
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'; |