Skip to content

Invalid cast between incompatible types for std::gmtime argument #426

@plexoos

Description

@plexoos

Describe the bug

The cast between unrelated types (as the one shown below) is not safe when the sizes of unsigned and time_t are different:

unsigned int ts_cast = ts;
struct tm *tm_cast = gmtime((time_t*) &ts_cast)

On our target system the sizes of the two types happened to be the same when using the -m32 compiler option but differ for -m64

This case was found in StRoot/StDaqLib/SSD/SSD_Reader.cxx due to the failed test 24. The log from the job. More specifically,

bfc.C(20, "P2005,tofDat,logger,MakeEvent,ITTF,ssddat,spt,SsdIt,SvtIt,pmdRaw,OShortR,OSpaceZ2", "/star/rcf/test/daq/2005/048/st_physics_6048025_raw_1020002.daq")

To Reproduce

Here is a small program to demonstrate the problem:

#include <ctime>
#include <iostream>
#include <vector>

using namespace std;

int main ()
{
  // $ date -d  @1108647599
  // Thu Feb 17 08:39:59 EST 2005

  cout << "sizeof(unsigned): " << sizeof(unsigned) << '\n';
  cout << "sizeof(time_t):   " << sizeof(time_t) << '\n';

  for (int ts : vector<int>{0, 5*24*3600+33, 1108647599})
  {
    time_t ts_nocast = ts;
    struct tm *tm_nocast = gmtime(&ts_nocast);
  
    unsigned int ts_cast = ts;
    struct tm *tm_cast = gmtime((time_t*) &ts_cast);

    cout << "tm_cast:   " << asctime(tm_cast);
    cout << "tm_nocast: " << asctime(tm_nocast);
  }

  return 0;

The erroneous output can be seen when comparing the -m32 and -m64 options respectively:
https://godbolt.org/z/xs9oezxro
https://godbolt.org/z/h3M5Pvq7f

Expected behavior

gmtime should return a valid date for the given Unix time when compiled with either -m32 or -m64 options

PS Many thanks to @veprbl for private discussion

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions