From: Wlodek Wencel Date: Thu, 23 Jul 2026 13:42:50 +0000 (+0200) Subject: [#4667] Fix null deref in getInterfacesKea X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=472079e68a32a5baa1bb65cdc3cd5cbd99b4c2d9;p=thirdparty%2Fkea.git [#4667] Fix null deref in getInterfacesKea Return early when interfaces-config is absent instead of calling empty() on a null ElementPtr. Closes #4667 Co-authored-by: Cursor --- diff --git a/changelog_unreleased/4667-getinterfaceskea-dereferences-null-elementptr-when-interfaces-config-is-absent b/changelog_unreleased/4667-getinterfaceskea-dereferences-null-elementptr-when-interfaces-config-is-absent new file mode 100644 index 0000000000..6600ec13f2 --- /dev/null +++ b/changelog_unreleased/4667-getinterfaceskea-dereferences-null-elementptr-when-interfaces-config-is-absent @@ -0,0 +1,5 @@ +[bug] wlodek + Fixed a null ElementPtr dereference in + TranslatorConfig::getInterfacesKea when the YANG + config has no interfaces-config node. + (Gitlab #4667) diff --git a/src/lib/yang/tests/config_unittests.cc b/src/lib/yang/tests/config_unittests.cc index 4e86d6af60..553bca4e7e 100644 --- a/src/lib/yang/tests/config_unittests.cc +++ b/src/lib/yang/tests/config_unittests.cc @@ -216,6 +216,32 @@ TEST_F(ConfigTestKeaV6, emptyKeaDhcp6) { EXPECT_TRUE(verify(emptyTreeKeaDhcp6)); } +// Regression: getConfig must not crash when interfaces-config is absent. +TEST_F(ConfigTestKeaV4, getConfigWithoutInterfacesConfig) { + ASSERT_NO_THROW_LOG(load(subnetTwoPoolsJson4)); + ConstElementPtr json; + ASSERT_NO_THROW_LOG(json = getJSON()); + ASSERT_TRUE(json); + ConstElementPtr dhcp4 = json->get("Dhcp4"); + ASSERT_TRUE(dhcp4); + EXPECT_FALSE(dhcp4->get("interfaces-config")); + ASSERT_TRUE(dhcp4->get("subnet4")); + EXPECT_EQ(1, dhcp4->get("subnet4")->size()); +} + +// Regression: getConfig must not crash when interfaces-config is absent. +TEST_F(ConfigTestKeaV6, getConfigWithoutInterfacesConfig) { + ASSERT_NO_THROW_LOG(load(subnetTimersJson6)); + ConstElementPtr json; + ASSERT_NO_THROW_LOG(json = getJSON()); + ASSERT_TRUE(json); + ConstElementPtr dhcp6 = json->get("Dhcp6"); + ASSERT_TRUE(dhcp6); + EXPECT_FALSE(dhcp6->get("interfaces-config")); + ASSERT_TRUE(dhcp6->get("subnet6")); + EXPECT_EQ(1, dhcp6->get("subnet6")->size()); +} + // Check subnet with two pools with ietf-dhcpv6-server model. // Validation will fail because the current model has a vendor-info // container with a mandatory ent-num leaf and no presence flag, diff --git a/src/lib/yang/translator_config.cc b/src/lib/yang/translator_config.cc index 25c2c952c4..7e217ea4a8 100644 --- a/src/lib/yang/translator_config.cc +++ b/src/lib/yang/translator_config.cc @@ -157,22 +157,24 @@ TranslatorConfig::getConfigControlKea(DataNode const& data_node) { ElementPtr TranslatorConfig::getInterfacesKea(DataNode const& config) { - ElementPtr result; optional const& interfaces_config_optional(config.findPath("interfaces-config")); - if (interfaces_config_optional) { - DataNode const interfaces_config(*interfaces_config_optional); - result = Element::createMap(); + if (!interfaces_config_optional) { + return (ElementPtr()); + } - checkAndGetLeaf(result, interfaces_config, "dhcp-socket-type"); - checkAndGetLeaf(result, interfaces_config, "interfaces"); - checkAndGetLeaf(result, interfaces_config, "outbound-interface"); - checkAndGetLeaf(result, interfaces_config, "re-detect"); - checkAndGetLeaf(result, interfaces_config, "service-sockets-max-retries"); - checkAndGetLeaf(result, interfaces_config, "service-sockets-require-all"); - checkAndGetLeaf(result, interfaces_config, "service-sockets-retry-wait-time"); + DataNode const interfaces_config(*interfaces_config_optional); + ElementPtr result = Element::createMap(); + + checkAndGetLeaf(result, interfaces_config, "dhcp-socket-type"); + checkAndGetLeaf(result, interfaces_config, "interfaces"); + checkAndGetLeaf(result, interfaces_config, "outbound-interface"); + checkAndGetLeaf(result, interfaces_config, "re-detect"); + checkAndGetLeaf(result, interfaces_config, "service-sockets-max-retries"); + checkAndGetLeaf(result, interfaces_config, "service-sockets-require-all"); + checkAndGetLeaf(result, interfaces_config, "service-sockets-retry-wait-time"); + + checkAndGetAndJsonifyLeaf(result, interfaces_config, "user-context"); - checkAndGetAndJsonifyLeaf(result, interfaces_config, "user-context"); - } return (result->empty() ? ElementPtr() : result); }