3

I'm asking this question more out of curiosity than actual need, but this has been baffling me for a while. I'd really like to know what's wrong with my code below. BTW don't try to understand the aim of the function - it's just meant to show the problem.

The code below causes a segmentation fault when run on Linux (using gcc), but it works just fine on Windows (using Visual Studio). As far as I know, there's nothing wrong with returning a struct by value, so what am I doing wrong below?

#include <time.h>
#include <stdint.h>

using namespace std;

struct tm testFunc(const uint32_t rawtime) {
  struct tm * localTime;
  localTime = gmtime ((const time_t*)&rawtime);
  struct tm testval = *localTime;
  return testval;
}

int main() {
  uint32_t now = 1538442104;
  testFunc(now);
}
6
  • 1
    @user1810087 You don't need to, well at least in C++, which this is tagged for for some reason Commented Oct 2, 2018 at 13:03
  • @Cliff, are you using C or C++? Commented Oct 2, 2018 at 13:04
  • The problem is in the testFunc() function. The main() function is just there to run the function. Also, I'm not using the return value of testFunc() on purpose here - just to show that it crashes anyway even if I don't try to use the returned value. Commented Oct 2, 2018 at 13:04
  • @NathanOliver I'm using C++ Commented Oct 2, 2018 at 13:05
  • 4
    Your time_t is not a uint32_t. This is undefined behavior. Read the manual pages. Commented Oct 2, 2018 at 13:06

2 Answers 2

3

time_t on Linux (at least on my RHEL6 box) is a signed long, which will be 64 bits in size on a 64 bit build. You're passing the address of an uint32_t, which means gmtime is reading four garbage bytes, invoking undefined behavior.

Windows seems to default to a 64 bit time_t as well, but it has the option to make it use a 32 bit type at the expense of triggering the Y2038 bug eventually. Either way, it might just work on Windows by coincidence (after all, undefined behavior can include "works as expected").

When the value is huge garbage, gmtime can end up returning NULL, which will cause a segfault if you attempt to read it.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! That was quick!
3

The gmtime line results in undefined behaviour. localTime = gmtime((const time_t*)&rawtime); is converting a uint32_t* to a time_t* but there is no guarantee the sizes are the same, indeed on many modern platforms time_t is 64bits.

If that does not crash it, then gmtime likely gets junk and then returns null, at which point the testval = *localtime will crash on reading from a null pointer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.