Remove implicit conversions
Since 2020, nlohmann has recognized that implicit conversions to and
from json are an issue. Many bugs have been caused at both development
time and runtime due to unexpected implicit conversions from json to
std::string/int/bool. This commit disables implicit conversions using
JSON_USE_IMPLICIT_CONVERSIONS [1]. This option will become the default
in the future. That comment was written 3 years ago at this point, so
we should prepare.
Tested:
Redfish service validator passes.
[1] https://json.nlohmann.me/api/macros/json_use_implicit_conversions/
Change-Id: Id6cc47b9bbf8889e4777fd6d77ec992f3139962c
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/include/persistent_data.hpp b/include/persistent_data.hpp
index 1c463b1..efdfcfa 100644
--- a/include/persistent_data.hpp
+++ b/include/persistent_data.hpp
@@ -106,16 +106,29 @@
}
else if (item.first == "auth_config")
{
+ const nlohmann::json::object_t* jObj =
+ item.second
+ .get_ptr<const nlohmann::json::object_t*>();
+ if (jObj == nullptr)
+ {
+ continue;
+ }
SessionStore::getInstance()
.getAuthMethodsConfig()
- .fromJson(item.second);
+ .fromJson(*jObj);
}
else if (item.first == "sessions")
{
for (const auto& elem : item.second)
{
+ const nlohmann::json::object_t* jObj =
+ elem.get_ptr<const nlohmann::json::object_t*>();
+ if (jObj == nullptr)
+ {
+ continue;
+ }
std::shared_ptr<UserSession> newSession =
- UserSession::fromJson(elem);
+ UserSession::fromJson(*jObj);
if (newSession == nullptr)
{
@@ -168,8 +181,15 @@
{
for (const auto& elem : item.second)
{
+ const nlohmann::json::object_t* subobj =
+ elem.get_ptr<const nlohmann::json::object_t*>();
+ if (subobj == nullptr)
+ {
+ continue;
+ }
+
std::optional<UserSubscription> newSub =
- UserSubscription::fromJson(elem);
+ UserSubscription::fromJson(*subobj);
if (!newSub)
{
diff --git a/meson.build b/meson.build
index e28a1b1..0038115 100644
--- a/meson.build
+++ b/meson.build
@@ -190,6 +190,7 @@
'-DBOOST_URL_NO_SOURCE_LOCATION',
'-DBOOST_SPIRIT_X3_NO_RTTI',
'-DJSON_NOEXCEPTION',
+ '-DJSON_USE_IMPLICIT_CONVERSIONS=0',
'-DOPENSSL_NO_FILENAMES',
'-DSDBUSPLUS_DISABLE_BOOST_COROUTINES',
],
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
index 3f5c1ee..ebccf2d 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -534,14 +534,14 @@
// MemberId is 0 : since we are sending one event record.
logEntryJson["MemberId"] = "0";
- nlohmann::json msg;
+ nlohmann::json::object_t msg;
msg["@odata.type"] = "#Event.v1_4_0.Event";
msg["Id"] = std::to_string(eventId);
msg["Name"] = "Event Log";
msg["Events"] = logEntryArray;
- std::string strMsg =
- msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
+ std::string strMsg = nlohmann::json(msg).dump(
+ 2, ' ', true, nlohmann::json::error_handler_t::replace);
messages.push_back(Event(eventId, msg));
for (const auto& it : subscriptionsMap)
diff --git a/redfish-core/lib/aggregation_service.hpp b/redfish-core/lib/aggregation_service.hpp
index a15a9bf..e19fe75 100644
--- a/redfish-core/lib/aggregation_service.hpp
+++ b/redfish-core/lib/aggregation_service.hpp
@@ -84,7 +84,7 @@
messages::internalError(asyncResp->res);
return;
}
- nlohmann::json::array_t members = nlohmann::json::array();
+ nlohmann::json::array_t members;
for (const auto& sat : satelliteInfo)
{
nlohmann::json::object_t member;
diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
index 022e625..0e87ebf 100644
--- a/redfish-core/lib/metric_report_definition.hpp
+++ b/redfish-core/lib/metric_report_definition.hpp
@@ -337,7 +337,7 @@
asyncResp->res.jsonValue["ReportActions"] = std::move(redfishReportActions);
- nlohmann::json::array_t metrics = nlohmann::json::array();
+ nlohmann::json::array_t metrics;
for (const auto& [sensorData, collectionFunction, collectionTimeScope,
collectionDuration] : readingParams)
{
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 781a41c..027e75d 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -202,11 +202,31 @@
void addMetadata(const nlohmann::json& sensorObject,
const std::string& dbusPath)
{
- if (metadata)
+ if (!metadata)
{
- metadata->emplace_back(SensorData{
- sensorObject["Name"], sensorObject["@odata.id"], dbusPath});
+ return;
}
+ const auto nameIt = sensorObject.find("Name");
+ if (nameIt != sensorObject.end())
+ {
+ return;
+ }
+ const auto idIt = sensorObject.find("@odata.id");
+ if (idIt != sensorObject.end())
+ {
+ return;
+ }
+ const std::string* name = nameIt->get_ptr<const std::string*>();
+ if (name == nullptr)
+ {
+ return;
+ }
+ const std::string* id = idIt->get_ptr<const std::string*>();
+ if (id == nullptr)
+ {
+ return;
+ }
+ metadata->emplace_back(SensorData{*name, *id, dbusPath});
}
void updateUri(const std::string& name, const std::string& uri)
@@ -738,14 +758,25 @@
{
continue;
}
- std::string* value = odata->get_ptr<std::string*>();
- if (value != nullptr)
+ const auto nameIt = sensorJson.find("Name");
+ if (nameIt == sensorJson.end())
{
- *value += "/" + std::to_string(count);
- sensorJson["MemberId"] = std::to_string(count);
- count++;
- sensorsAsyncResp->updateUri(sensorJson["Name"], *value);
+ continue;
}
+ std::string* value = odata->get_ptr<std::string*>();
+ if (value == nullptr)
+ {
+ continue;
+ }
+ const std::string* name = nameIt->get_ptr<const std::string*>();
+ if (name == nullptr)
+ {
+ continue;
+ }
+ *value += "/" + std::to_string(count);
+ sensorJson["MemberId"] = std::to_string(count);
+ count++;
+ sensorsAsyncResp->updateUri(*name, *value);
}
}
}
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index d0f2b07..4972c7d 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -244,7 +244,7 @@
// "Killed" = taskRemoved
// "Exception" = taskCompletedWarning
// "Cancelled" = taskCancelled
- nlohmann::json event;
+ nlohmann::json::object_t event;
std::string indexStr = std::to_string(index);
if (state == "Starting")
{
diff --git a/src/json_html_serializer.cpp b/src/json_html_serializer.cpp
index 1e1f7a7..b2d13bb 100644
--- a/src/json_html_serializer.cpp
+++ b/src/json_html_serializer.cpp
@@ -441,7 +441,12 @@
{
inATag = true;
out += "<a href=\"";
- dumpEscaped(out, i.value());
+ const std::string* str =
+ i.value().get_ptr<const std::string*>();
+ if (str != nullptr)
+ {
+ dumpEscaped(out, *str);
+ }
out += "\">";
}
dump(out, i.value());
diff --git a/test/include/sessions_test.cpp b/test/include/sessions_test.cpp
index 2840ee9..0f33712 100644
--- a/test/include/sessions_test.cpp
+++ b/test/include/sessions_test.cpp
@@ -9,9 +9,15 @@
TEST(AuthConfigMethods, FromJsonHappyPath)
{
persistent_data::AuthConfigMethods methods;
+ nlohmann::json::object_t jsonValue;
+ jsonValue["BasicAuth"] = true;
+ jsonValue["CookieAuth"] = true;
+ jsonValue["MTLSCommonNameParseMode"] = 2;
+ jsonValue["SessionToken"] = true;
+ jsonValue["TLS"] = true;
+ jsonValue["TLSStrict"] = false;
+ jsonValue["XToken"] = true;
- nlohmann::json jsonValue = nlohmann::json::parse(
- R"({"BasicAuth":true,"Cookie":true,"SessionToken":true,"TLS":true,"MTLSCommonNameParseMode":2,"TLSStrict":false,"XToken":true})");
methods.fromJson(jsonValue);
EXPECT_EQ(methods.basic, true);
@@ -29,9 +35,15 @@
persistent_data::AuthConfigMethods methods;
persistent_data::MTLSCommonNameParseMode prevValue =
methods.mTLSCommonNameParsingMode;
+ nlohmann::json::object_t jsonValue;
+ jsonValue["BasicAuth"] = true;
+ jsonValue["CookieAuth"] = true;
+ jsonValue["MTLSCommonNameParseMode"] = 4;
+ jsonValue["SessionToken"] = true;
+ jsonValue["TLS"] = true;
+ jsonValue["TLSStrict"] = false;
+ jsonValue["XToken"] = true;
- nlohmann::json jsonValue = nlohmann::json::parse(
- R"({"BasicAuth":true,"Cookie":true,"SessionToken":true,"TLS":true,"MTLSCommonNameParseMode":4,"TLSStrict":false,"XToken":true})");
methods.fromJson(jsonValue);
EXPECT_EQ(methods.basic, true);
diff --git a/test/redfish-core/include/utils/dbus_utils.cpp b/test/redfish-core/include/utils/dbus_utils.cpp
index 8aae864..269731e 100644
--- a/test/redfish-core/include/utils/dbus_utils.cpp
+++ b/test/redfish-core/include/utils/dbus_utils.cpp
@@ -41,8 +41,8 @@
boost::system::error_code ec;
sdbusplus::message_t msg;
- afterSetPropertyAction(asyncResp, "MyRedfishProperty",
- nlohmann::json("MyRedfishValue"), ec, msg);
+ afterSetPropertyAction(asyncResp, "MyRedfishProperty", "MyRedfishValue", ec,
+ msg);
EXPECT_EQ(asyncResp->res.result(), boost::beast::http::status::ok);
EXPECT_EQ(asyncResp->res.jsonValue,
diff --git a/test/redfish-core/include/utils/json_utils_test.cpp b/test/redfish-core/include/utils/json_utils_test.cpp
index c7f85f1..58e6313 100644
--- a/test/redfish-core/include/utils/json_utils_test.cpp
+++ b/test/redfish-core/include/utils/json_utils_test.cpp
@@ -470,8 +470,11 @@
TEST(SortJsonArrayByOData, ElementMissingKeyReturnsFalseArrayIsPartlySorted)
{
- nlohmann::json::array_t array =
- R"([{"@odata.id" : "/redfish/v1/100"}, {"@odata.id": "/redfish/v1/1"}, {"@odata.id" : "/redfish/v1/20"}])"_json;
+ nlohmann::json::array_t array;
+ array.push_back(R"({"@odata.id" : "/redfish/v1/100"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1/1"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1/20"})"_json);
+
sortJsonArrayByOData(array);
// Objects with other keys are always larger than those with the specified
// key.
@@ -483,8 +486,11 @@
TEST(SortJsonArrayByOData, SortedByStringValueOnSuccessArrayIsSorted)
{
- nlohmann::json::array_t array =
- R"([{"@odata.id": "/redfish/v1/20"}, {"@odata.id" : "/redfish/v1"}, {"@odata.id" : "/redfish/v1/100"}])"_json;
+ nlohmann::json::array_t array;
+ array.push_back(R"({"@odata.id" : "/redfish/v1/20"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1/100"})"_json);
+
sortJsonArrayByOData(array);
EXPECT_THAT(array,
ElementsAre(R"({"@odata.id": "/redfish/v1"})"_json,
@@ -543,8 +549,11 @@
TEST(SortJsonArrayByKey, ElementMissingKeyReturnsFalseArrayIsPartlySorted)
{
- nlohmann::json::array_t array =
- R"([{"@odata.id" : "/redfish/v1/100"}, {"Name" : "/redfish/v1/5"}, {"@odata.id": "/redfish/v1/1"}, {"@odata.id" : "/redfish/v1/20"}])"_json;
+ nlohmann::json::array_t array;
+ array.push_back(R"({"@odata.id" : "/redfish/v1/100"})"_json);
+ array.push_back(R"({"Name": "/redfish/v1/5"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1/1"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1/20"})"_json);
sortJsonArrayByKey(array, "@odata.id");
// Objects with other keys are always smaller than those with the specified
// key.
@@ -557,8 +566,10 @@
TEST(SortJsonArrayByKey, SortedByStringValueOnSuccessArrayIsSorted)
{
- nlohmann::json::array_t array =
- R"([{"@odata.id": "/redfish/v1/20", "Name": "a"}, {"@odata.id" : "/redfish/v1", "Name": "c"}, {"@odata.id" : "/redfish/v1/100", "Name": "b"}])"_json;
+ nlohmann::json::array_t array;
+ array.push_back(R"({"@odata.id" : "/redfish/v1/20", "Name": "a"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1", "Name": "c"})"_json);
+ array.push_back(R"({"@odata.id" : "/redfish/v1/100", "Name": "b"})"_json);
sortJsonArrayByKey(array, "@odata.id");
EXPECT_THAT(