Clean up Crashdump log entry creation
To avoid passing references to bad memory locations, we had to
pre-build the array with empty entries so we could pass a
reference to the array index without it changing later.
This changes so the code that fills the log entry object checks
if it's filling a single entry or an array entry and expands
the array at that time.
This simplifies filling the "Members" array in the Crashdump
entry collection and avoids sending references to an array
index.
Tested:
Confirmed that Crashdump LogEntries are correctly filled in
the "Members" array of the collection and in the individual
LogEntry.
Change-Id: I4484e248b6d72fadbaedcbb27840cd46cfe3b323
Signed-off-by: Jason M. Bills <jason.m.bills@intel.com>
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 154de95..8dcf7da 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -2651,7 +2651,7 @@
std::string crashdumpURI =
"/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" +
logID + "/" + filename;
- logEntryJson = {
+ nlohmann::json logEntry = {
{"@odata.type", "#LogEntry.v1_7_0.LogEntry"},
{"@odata.id",
"/redfish/v1/Systems/system/LogServices/Crashdump/Entries/" +
@@ -2663,6 +2663,20 @@
{"DiagnosticDataType", "OEM"},
{"OEMDiagnosticDataType", "PECICrashdump"},
{"Created", std::move(timestamp)}};
+
+ // If logEntryJson references an array of LogEntry resources
+ // ('Members' list), then push this as a new entry, otherwise set it
+ // directly
+ if (logEntryJson.is_array())
+ {
+ logEntryJson.push_back(logEntry);
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ logEntryJson.size();
+ }
+ else
+ {
+ logEntryJson = logEntry;
+ }
};
crow::connections::systemBus->async_method_call(
std::move(getStoredLogCallback), crashdumpObject,
@@ -2686,61 +2700,45 @@
boost::beast::http::verb::
get)([](const crow::Request&,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- // Collections don't include the static data added by SubRoute
- // because it has a duplicate entry for members
- auto getLogEntriesCallback = [asyncResp](
- const boost::system::error_code ec,
- const std::vector<std::string>&
- resp) {
- if (ec)
- {
- if (ec.value() !=
- boost::system::errc::no_such_file_or_directory)
- {
- BMCWEB_LOG_DEBUG << "failed to get entries ec: "
- << ec.message();
- messages::internalError(asyncResp->res);
- return;
- }
- }
- asyncResp->res.jsonValue["@odata.type"] =
- "#LogEntryCollection.LogEntryCollection";
- asyncResp->res.jsonValue["@odata.id"] =
- "/redfish/v1/Systems/system/LogServices/Crashdump/Entries";
- asyncResp->res.jsonValue["Name"] = "Open BMC Crashdump Entries";
- asyncResp->res.jsonValue["Description"] =
- "Collection of Crashdump Entries";
- nlohmann::json& logEntryArray =
- asyncResp->res.jsonValue["Members"];
- logEntryArray = nlohmann::json::array();
- std::vector<std::string> logIDs;
- // Get the list of log entries and build up an empty array big
- // enough to hold them
- for (const std::string& objpath : resp)
- {
- // Get the log ID
- std::size_t lastPos = objpath.rfind('/');
- if (lastPos == std::string::npos)
- {
- continue;
- }
- logIDs.emplace_back(objpath.substr(lastPos + 1));
-
- // Add a space for the log entry to the array
- logEntryArray.push_back({});
- }
- // Now go through and set up async calls to fill in the entries
- size_t index = 0;
- for (const std::string& logID : logIDs)
- {
- // Add the log entry to the array
- logCrashdumpEntry(asyncResp, logID, logEntryArray[index++]);
- }
- asyncResp->res.jsonValue["Members@odata.count"] =
- logEntryArray.size();
- };
crow::connections::systemBus->async_method_call(
- std::move(getLogEntriesCallback),
+ [asyncResp](const boost::system::error_code ec,
+ const std::vector<std::string>& resp) {
+ if (ec)
+ {
+ if (ec.value() !=
+ boost::system::errc::no_such_file_or_directory)
+ {
+ BMCWEB_LOG_DEBUG << "failed to get entries ec: "
+ << ec.message();
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogEntryCollection.LogEntryCollection";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Systems/system/LogServices/Crashdump/Entries";
+ asyncResp->res.jsonValue["Name"] =
+ "Open BMC Crashdump Entries";
+ asyncResp->res.jsonValue["Description"] =
+ "Collection of Crashdump Entries";
+ asyncResp->res.jsonValue["Members"] =
+ nlohmann::json::array();
+
+ for (const std::string& path : resp)
+ {
+ const sdbusplus::message::object_path objPath(path);
+ // Get the log ID
+ std::string logID = objPath.filename();
+ if (logID.empty())
+ {
+ continue;
+ }
+ // Add the log entry to the array
+ logCrashdumpEntry(asyncResp, logID,
+ asyncResp->res.jsonValue["Members"]);
+ }
+ },
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
"xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "", 0,