Reduce usage of std::time_t, std::chrono::system_clock::to_time_t and system_clock::from_time_t in order to get correct dates when working with a 32bit application by MarchMore · Pull Request #401 · Thalhammer/jwt-cpp
Fixing a potential "year 2038 problem" occurrence in "jwt.h".
This one seems to happen when using the library in 32-bit applications. The main problem is not the architecture itself, but the usage of "std::time_t" from "" instead of chrono-only utils in the "jwt-cpp" library.
I've added an example here in which the difference between 32-bit and 64-bit compilation can be seen clearly:
- Create token with "exp" of different dates
- Convert data to string
- Convert string to data
- See that "exp" (for year >2038) gets negative --> Which means basically "token expired"
https://godbolt.org/z/9GGqM577W
Code:
#include <chrono> #include <iostream> #include "jwt-cpp/jwt.h" void analyze(std::chrono::hours hours_from_now) { std::string token = jwt::create().set_expires_at(std::chrono::system_clock::now() + hours_from_now).sign(jwt::algorithm::none{}); std::chrono::system_clock::time_point exp = jwt::decode(token).get_expires_at(); std::cout << std::chrono::duration_cast<std::chrono::seconds>(exp.time_since_epoch()).count() << "\n"; } int main() { // Testing conversion of token with "exp" to string and back to data again std::cout << "Tests:\n"; analyze(std::chrono::hours(24 * 365 * 0)); // Today analyze(std::chrono::hours(24 * 365 * 1)); // Today + 1 year analyze(std::chrono::hours(24 * 365 * 10)); // Today + 10 years analyze(std::chrono::hours(24 * 365 * 20)); // Today + 20 years (Potential "year 2038 problem") // Looking onto the problem: // Today + 20 years (Potential "year 2038 problem") const auto problematic_time_point = std::chrono::system_clock::now() + std::chrono::hours(24 * 365 * 20); // When converting to "std::time_t" (And so using <ctime>) std::cout << "\nSee problem:\n"; long long time1 = std::chrono::system_clock::to_time_t(problematic_time_point); std::cout << time1 << "\n"; // When converting to "std::chrono::duration_cast" (Using <chrono> only) std::cout << "\nSee solution:\n"; long long time2 = std::chrono::duration_cast<std::chrono::seconds>(problematic_time_point.time_since_epoch()).count(); std::cout << time2 << "\n"; return 0; }
Result (32-bit):
Tests:
1763856625
1795392625
2079216625
-1900390671
See problem:
-1900390671
See solution:
2394576625
Result (64-bit):
Tests:
1763856626
1795392626
2079216626
2394576626
See problem:
2394576626
See solution:
2394576626