fix the year 2038 problem in getDateTime
The existing codes cast uint64_t into time_t which is int32_t in
most 32-bit systems. It results overflow if the timestamp is larger
than INT_MAX.
time_t will be 64 bits in future releases of glibc. See
https://sourceware.org/bugzilla/show_bug.cgi?id=28182.
This change workarounds the year 2038 problem via boost's ptime.
std::chrono doesn't help since it is still 32 bits.
Tested on QEMU.
Example output for certificate:
{
"Name": "HTTPS Certificate",
"Subject": null,
"ValidNotAfter": "2106-01-28T20:40:31Z",
"ValidNotBefore": "2106-02-06T18:28:16Z"
}
Previously, the format is like "1969-12-31T12:00:00+00:00". Note
that the ending "+00:00" is the time zone, not ms.
Tested the schema on QEMU. No new Redfish Service Validator errors.
Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: I8ef0bee3d724184d96253c23f3919447828d3f82
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index 045426e..8a78317 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -643,9 +643,8 @@
std::get_if<uint64_t>(&property.second);
if (value)
{
- std::time_t time = static_cast<std::time_t>(*value);
asyncResp->res.jsonValue["ValidNotAfter"] =
- crow::utility::getDateTime(time);
+ crow::utility::getDateTimeUint(*value);
}
}
else if (property.first == "ValidNotBefore")
@@ -654,9 +653,8 @@
std::get_if<uint64_t>(&property.second);
if (value)
{
- std::time_t time = static_cast<std::time_t>(*value);
asyncResp->res.jsonValue["ValidNotBefore"] =
- crow::utility::getDateTime(time);
+ crow::utility::getDateTimeUint(*value);
}
}
}
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index fb515fe..074c927 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -180,8 +180,7 @@
<< strerror(-ret);
return false;
}
- entryTimestamp = crow::utility::getDateTime(
- static_cast<std::time_t>(timestamp / 1000 / 1000));
+ entryTimestamp = crow::utility::getDateTimeUint(timestamp / 1000 / 1000);
return true;
}
@@ -419,7 +418,7 @@
{
continue;
}
- std::time_t timestamp;
+ uint64_t timestamp = 0;
uint64_t size = 0;
std::string dumpStatus;
nlohmann::json thisEntry;
@@ -485,8 +484,7 @@
messages::internalError(asyncResp->res);
break;
}
- timestamp =
- static_cast<std::time_t>(*usecsTimeStamp);
+ timestamp = (*usecsTimeStamp / 1000 / 1000);
break;
}
}
@@ -505,7 +503,8 @@
thisEntry["@odata.id"] = dumpPath + entryID;
thisEntry["Id"] = entryID;
thisEntry["EntryType"] = "Event";
- thisEntry["Created"] = crow::utility::getDateTime(timestamp);
+ thisEntry["Created"] =
+ crow::utility::getDateTimeUint(timestamp);
thisEntry["Name"] = dumpType + " Dump Entry";
thisEntry["AdditionalDataSizeBytes"] = size;
@@ -578,7 +577,7 @@
}
foundDumpEntry = true;
- std::time_t timestamp;
+ uint64_t timestamp = 0;
uint64_t size = 0;
std::string dumpStatus;
@@ -635,8 +634,7 @@
messages::internalError(asyncResp->res);
break;
}
- timestamp =
- static_cast<std::time_t>(*usecsTimeStamp);
+ timestamp = *usecsTimeStamp / 1000 / 1000;
break;
}
}
@@ -660,7 +658,7 @@
asyncResp->res.jsonValue["Id"] = entryID;
asyncResp->res.jsonValue["EntryType"] = "Event";
asyncResp->res.jsonValue["Created"] =
- crow::utility::getDateTime(timestamp);
+ crow::utility::getDateTimeUint(timestamp);
asyncResp->res.jsonValue["Name"] = dumpType + " Dump Entry";
asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
@@ -1490,9 +1488,9 @@
thisEntry["Severity"] =
translateSeverityDbusToRedfish(*severity);
thisEntry["Created"] =
- crow::utility::getDateTime(timestamp);
+ crow::utility::getDateTimeStdtime(timestamp);
thisEntry["Modified"] =
- crow::utility::getDateTime(updateTimestamp);
+ crow::utility::getDateTimeStdtime(updateTimestamp);
if (filePath != nullptr)
{
thisEntry["AdditionalDataURI"] =
@@ -1628,9 +1626,9 @@
asyncResp->res.jsonValue["Severity"] =
translateSeverityDbusToRedfish(*severity);
asyncResp->res.jsonValue["Created"] =
- crow::utility::getDateTime(timestamp);
+ crow::utility::getDateTimeStdtime(timestamp);
asyncResp->res.jsonValue["Modified"] =
- crow::utility::getDateTime(updateTimestamp);
+ crow::utility::getDateTimeStdtime(updateTimestamp);
if (filePath != nullptr)
{
asyncResp->res.jsonValue["AdditionalDataURI"] =
@@ -3154,8 +3152,8 @@
// Get the Created time from the timestamp
std::string entryTimeStr;
- entryTimeStr = crow::utility::getDateTime(
- static_cast<std::time_t>(usecSinceEpoch / 1000 / 1000));
+ entryTimeStr =
+ crow::utility::getDateTimeUint(usecSinceEpoch / 1000 / 1000);
// assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex)
std::ostringstream hexCode;
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 12af99d..ca5d8c5 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -1739,12 +1739,11 @@
}
// LastRebootTime is epoch time, in milliseconds
// https://github.com/openbmc/phosphor-dbus-interfaces/blob/7f9a128eb9296e926422ddc312c148b625890bb6/xyz/openbmc_project/State/BMC.interface.yaml#L19
- time_t lastResetTimeStamp =
- static_cast<time_t>(*lastResetTimePtr / 1000);
+ uint64_t lastResetTimeStamp = *lastResetTimePtr / 1000;
// Convert to ISO 8601 standard
aResp->res.jsonValue["LastResetTime"] =
- crow::utility::getDateTime(lastResetTimeStamp);
+ crow::utility::getDateTimeUint(lastResetTimeStamp);
},
"xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0",
"org.freedesktop.DBus.Properties", "Get",
diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
index c959495..5ecab77 100644
--- a/redfish-core/lib/metric_report.hpp
+++ b/redfish-core/lib/metric_report.hpp
@@ -26,8 +26,7 @@
{"MetricId", id},
{"MetricProperty", metadata},
{"MetricValue", std::to_string(sensorValue)},
- {"Timestamp",
- crow::utility::getDateTime(static_cast<time_t>(timestamp))},
+ {"Timestamp", crow::utility::getDateTimeUint(timestamp)},
});
}
@@ -53,8 +52,7 @@
}
const auto& [timestamp, readings] = *timestampReadings;
- json["Timestamp"] =
- crow::utility::getDateTime(static_cast<time_t>(timestamp));
+ json["Timestamp"] = crow::utility::getDateTimeUint(timestamp);
json["MetricValues"] = toMetricValues(readings);
return true;
}
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index 2f88a77..8e1a6f4 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -1171,12 +1171,11 @@
}
// LastStateChangeTime is epoch time, in milliseconds
// https://github.com/openbmc/phosphor-dbus-interfaces/blob/33e8e1dd64da53a66e888d33dc82001305cd0bf9/xyz/openbmc_project/State/Chassis.interface.yaml#L19
- time_t lastResetTimeStamp =
- static_cast<time_t>(*lastResetTimePtr / 1000);
+ uint64_t lastResetTimeStamp = *lastResetTimePtr / 1000;
// Convert to ISO 8601 standard
aResp->res.jsonValue["LastResetTime"] =
- crow::utility::getDateTime(lastResetTimeStamp);
+ crow::utility::getDateTimeUint(lastResetTimeStamp);
},
"xyz.openbmc_project.State.Chassis",
"/xyz/openbmc_project/state/chassis0",
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 22e9743..b7795a7 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -388,11 +388,11 @@
asyncResp->res.jsonValue["Name"] = "Task " + strParam;
asyncResp->res.jsonValue["TaskState"] = ptr->state;
asyncResp->res.jsonValue["StartTime"] =
- crow::utility::getDateTime(ptr->startTime);
+ crow::utility::getDateTimeStdtime(ptr->startTime);
if (ptr->endTime)
{
asyncResp->res.jsonValue["EndTime"] =
- crow::utility::getDateTime(*(ptr->endTime));
+ crow::utility::getDateTimeStdtime(*(ptr->endTime));
}
asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
asyncResp->res.jsonValue["Messages"] = ptr->messages;