HowardHinnant / date

A date and time library based on the C++11/14/17 <chrono> header
Other
3.08k stars 670 forks source link

Undefined behaviour when formatting very large negative timestamp #696

Closed pitrou closed 2 years ago

pitrou commented 2 years ago

Reproducible using:

void ubformat() {
  const auto epoch = date::sys_days{date::jan / 1 / 1970};
  for (const int64_t ticks : {std::numeric_limits<int64_t>::max(),
                              std::numeric_limits<int64_t>::min()}) {
    const auto t = epoch + std::chrono::nanoseconds{ticks};
    std::cout << date::format("%F %T", t) << std::endl;
  }
}

Here is the output using gcc 9.3.0 and -fsanitize=undefined:

2262-04-11 23:47:16.854775807
/usr/include/c++/9/chrono:166:38: runtime error: signed integer overflow: -9223372800 * 1000000000 cannot be represented in type 'long int'
/usr/include/c++/9/chrono:469:34: runtime error: signed integer overflow: -9223372036854775808 - 9223371273709551616 cannot be represented in type 'long int'
1677-09-21 00:12:43.145224192

I'm not sure how important this issue may be considered, but I thought it may be useful to report it anyway.

Note the line producing the undefined behaviour warnings is really the date::format line. If you try to replace with e.g. t.time_since_epoch().count(), the warnings disappear.

HowardHinnant commented 2 years ago

I was able to fix this one.

pitrou commented 2 years ago

Thank you for the fast update!