Skip to content

Conversation

@MarchMore
Copy link

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:

  1. Create token with "exp" of different dates
  2. Convert data to string
  3. Convert string to data
  4. 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

… system_clock::from_time_t in order to get correct dates when working with a 32bit application
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant