From af187d1bc27a7390b358d7ad3b9f8f44cabe41ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Thu, 20 Nov 2025 12:46:49 +0100 Subject: [PATCH 7/7] don't segfault when listing module's features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Organization: Wires This is especially relevant when working with the "printed context" from sysrepo, because that context has all the parsed info removed. As a result, it is not possible to query a module's list of features. Let's stop dereferencing a null pointer in that case. Bug: https://github.com/sysrepo/sysrepo/issues/3695 Change-Id: I6258f580b4e5aa02cae2d60260b84593aefcf587 Signed-off-by: Mattias Walström --- CMakeLists.txt | 1 + include/libyang-cpp/Utils.hpp | 1 + src/Module.cpp | 3 +++ src/utils/exception.cpp | 5 +++++ tests/context.cpp | 12 ++++++++++++ 5 files changed, 22 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cbaf82a..b9da66b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,7 @@ if(BUILD_TESTING) endfunction() libyang_cpp_test(context) + target_link_libraries(test_context PkgConfig::LIBYANG) libyang_cpp_test(data_node) target_link_libraries(test_data_node PkgConfig::LIBYANG) libyang_cpp_test(schema_node) diff --git a/include/libyang-cpp/Utils.hpp b/include/libyang-cpp/Utils.hpp index 934714d..428b265 100644 --- a/include/libyang-cpp/Utils.hpp +++ b/include/libyang-cpp/Utils.hpp @@ -35,6 +35,7 @@ public: class LIBYANG_CPP_EXPORT ParsedInfoUnavailable : public Error { public: explicit ParsedInfoUnavailable(); + explicit ParsedInfoUnavailable(const std::string& what); }; /** diff --git a/src/Module.cpp b/src/Module.cpp index d6d4023..8eb8fb4 100644 --- a/src/Module.cpp +++ b/src/Module.cpp @@ -155,6 +155,9 @@ void Module::setImplemented(const AllFeatures) */ std::vector Module::features() const { + if (!m_module->parsed) { + throw ParsedInfoUnavailable{"Module::features: lys_module::parsed is not available"}; + } std::vector res; for (const auto& feature : std::span(m_module->parsed->features, LY_ARRAY_COUNT(m_module->parsed->features))) { res.emplace_back(Feature{&feature, m_ctx}); diff --git a/src/utils/exception.cpp b/src/utils/exception.cpp index ecd2b85..a8d908b 100644 --- a/src/utils/exception.cpp +++ b/src/utils/exception.cpp @@ -22,6 +22,11 @@ ParsedInfoUnavailable::ParsedInfoUnavailable() { } +ParsedInfoUnavailable::ParsedInfoUnavailable(const std::string& what) + : Error(what) +{ +} + ErrorCode ErrorWithCode::code() const { return m_errCode; diff --git a/tests/context.cpp b/tests/context.cpp index 355860b..5fce0f4 100644 --- a/tests/context.cpp +++ b/tests/context.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "example_schema.hpp" #include "pretty_printers.hpp" #include "test_vars.hpp" @@ -333,6 +334,17 @@ TEST_CASE("context") REQUIRE(enabledFeatures == expectedEnabledFeatures); } + DOCTEST_SUBCASE("printed context") + { + ctx->setSearchDir(TESTS_DIR / "yang"); + auto mod = ctx->loadModule("mod1", std::nullopt, {"*"}); + REQUIRE(mod.features().size() == 3); + ly_ctx_free_parsed(retrieveContext(*ctx)); + REQUIRE_THROWS_WITH_AS(mod.features(), + "Module::features: lys_module::parsed is not available", + libyang::ParsedInfoUnavailable); + } + DOCTEST_SUBCASE("Module::setImplemented") { ctx->setSearchDir(TESTS_DIR / "yang"); -- 2.43.0