main: Fix getSubTree & getSubTreePaths partial match
Due to us popping out the trailing "/" in our "reqPath", partial matches
satisfied the "boost::starts_with(" searches for paths - leading to
"core1X" for example, matching a reqPath of "core1" or "core1/".
Since we do not want to return the base reqPath anyway, add a trailing
"/" in the reqPath for the match to ensure complete match.
Tested:
dbus-send --system --print-reply --dest=xyz.openbmc_project.ObjectMapper /xyz/openbmc_project/object_mapper xyz.openbmc_project.ObjectMapper.GetSubTreePaths string:"/xyz/openbmc_oject/inventory/system/chassis/motherboard/cpu0/core1" int32:0 array:string:"xyz.openbmc_project.Inventory.Item.CpuThread"
Without the fix:
array [
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core1/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core11/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core12/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core13/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core14/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core15/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core16/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core17/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core18/thread0"
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core19/thread0"
]
With the fix:
array [
string "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0/core1/thread0"
]
Similar results with GetSubTree, results not pasted as it's too long:
dbus-send --system --print-reply --dest=xyz.openbmc_project.ObjectMapper /xyz/openbmc_project/object_mapper xyz.openbmc_project.ObjectMapper.GetSubTree string:"/xyz/openbmc_proje/inventory/system/chassis/motherboard/cpu0/core1" int32:0 array:string:"xyz.openbmc_project.Inventory.Item.CpuThread"
-------------
Also verified that "depth" remained the same using print outs:
Before change:
mapperx[12580]: thisPath: /xyz/openbmc_project/sensors/power
mapperx[12580]: reqPath:
mapperx[12580]: thisDepth: 4
mapperx[12580]: thisPath: /xyz/openbmc_project/sensors/temperature
mapperx[12580]: reqPath: /xyz/openbmc_project
mapperx[12580]: thisDepth: 2
After:
mapperx[30959]: thisPath: /xyz/openbmc_project/network
mapperx[30959]: reqPath: /
mapperx[30959]: thisDepth: 3
mapperx[30959]: thisPath: /xyz/openbmc_project/inventory/system/board
mapperx[30959]: reqPath: /xyz/openbmc_project/inventory/system/
mapperx[30959]: thisDepth: 1
Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: If488402a3839de21c50b4585e51fa156016e768d
diff --git a/src/main.cpp b/src/main.cpp
index 64031b8..1e3883f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,6 +18,8 @@
#include <exception>
#include <iomanip>
#include <iostream>
+#include <string>
+#include <string_view>
#include <utility>
AssociationMaps associationMaps;
@@ -545,11 +547,17 @@
// Interfaces need to be sorted for intersect to function
std::sort(interfaces.begin(), interfaces.end());
- if (boost::ends_with(reqPath, "/"))
+ // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
+ // will be guaranteed not to have a trailing "/"
+ if (!boost::ends_with(reqPath, "/"))
{
- reqPath.pop_back();
+ reqPath += "/";
}
- if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
+ std::string_view reqPathStripped =
+ std::string_view(reqPath).substr(0, reqPath.size() - 1);
+
+ if (!reqPathStripped.empty() &&
+ interfaceMap.find(reqPathStripped) == interfaceMap.end())
{
throw sdbusplus::xyz::openbmc_project::Common::Error::
ResourceNotFound();
@@ -560,16 +568,17 @@
{
const auto& thisPath = objectPath.first;
- if (thisPath == reqPath)
+ // Skip exact match on stripped search term
+ if (thisPath == reqPathStripped)
{
continue;
}
if (boost::starts_with(thisPath, reqPath))
{
- // count the number of slashes past the search term
- int32_t thisDepth = std::count(thisPath.begin() + reqPath.size(),
- thisPath.end(), '/');
+ // count the number of slashes past the stripped search term
+ int32_t thisDepth = std::count(
+ thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
if (thisDepth <= depth)
{
for (const auto& interfaceMap : objectPath.second)
@@ -600,11 +609,17 @@
// Interfaces need to be sorted for intersect to function
std::sort(interfaces.begin(), interfaces.end());
- if (boost::ends_with(reqPath, "/"))
+ // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
+ // will be guaranteed not to have a trailing "/"
+ if (!boost::ends_with(reqPath, "/"))
{
- reqPath.pop_back();
+ reqPath += "/";
}
- if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
+ std::string_view reqPathStripped =
+ std::string_view(reqPath).substr(0, reqPath.size() - 1);
+
+ if (!reqPathStripped.empty() &&
+ interfaceMap.find(reqPathStripped) == interfaceMap.end())
{
throw sdbusplus::xyz::openbmc_project::Common::Error::
ResourceNotFound();
@@ -615,16 +630,17 @@
{
const auto& thisPath = objectPath.first;
- if (thisPath == reqPath)
+ // Skip exact match on stripped search term
+ if (thisPath == reqPathStripped)
{
continue;
}
if (boost::starts_with(thisPath, reqPath))
{
- // count the number of slashes past the search term
- int thisDepth = std::count(thisPath.begin() + reqPath.size(),
- thisPath.end(), '/');
+ // count the number of slashes past the stripped search term
+ int thisDepth = std::count(
+ thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
if (thisDepth <= depth)
{
bool add = interfaces.empty();