Saturday, March 5, 2016

Unix timestamps and the year 2038 problem


Recently I read a couple of news articles about the Y2038 bug. That is, the year 2038 problem. The news -as often- had exaggerated this problem to the level that they claimed computers might be wiped out. So, I decided to write an article to explain what the issue really is.

32-bit unix systems represent time values as a signed 32 bit integer. So, if you want to store timestamp in your program, a signed 32 bit integer is used for that. The actual value stored in this integer is 'number of seconds passed since a known and fixed moment in the past'. This moment is known as "epoch" and is fixed on - 00:00:00 UTC on 1 January 1970. So basically, unix timestamps store a specific time as number of seconds passed since epoch to that moment.

For example, if I want to store this time - 00:00:00 - 1 January 1972 - in a unix timestamp, it will simply be written as integer - 63072000. This is the number of seconds between 1 January 1970 and 1 January 1972 i.e. number of seconds in 2 years.

Now, let's consider binary representation of this.
Since timestamps are 32 bit signed integers, they will be represented something like this -
0 0000000 10111010 00101110 10011110
Note that the leftmost digit is sign digit.

At each second, the value of this timestamp increases by 1. After some years, at 03:14:07 UTC on 19 January 2038 to be precise, value of this timestamp will go something like this

0 1111111 11111111 11111111 11111101          at 03:14:05
0 1111111 11111111 11111111 11111110          at 03:14:06
0 1111111 11111111 11111111 11111111          at 03:14:07
1 0000000 00000000 00000000 00000000          at 03:14:08
1 0000000 00000000 00000000 00000001          at 03:14:09

Did you notice what happened here? the integer representing time filled up all the memory allocated to it (31 bits to be precise) and wrote into the 32nd bit which is used to indicate sign. This is a typical integer overflow problem. 

After this point, since the sign bit is now set, unix systems will start reporting time as -1, -2, -3, -4 and so on...
This is obviously wrong and many systems which read or are dependant on time will crash.

Manifestations of this problem can occur in more places than you think. Embedded systems generally use this 32-bit timestamp and run the risk of running into Y2038 problem. Moreover, from my knowledge, they are not easily upgradable.

Also many file systems and databases implement the 32 bit timestamps. One specific example is MySQL, which has an inbuilt function to return the current 32bit timestamp. Needless to say, those who won't upgrade their MySQL deployments might see their applications go crazy on d-day :)

The solutions to this problem are not without a lot of compatibility issues. Changing the data type of timestamps from 32 bit signed integer to 32 bit unsigned will extend the validity of timestamps to ~2100, but this won't work with systems which need to store time before epoch - 1970. Another approach - changing the representation from 32-bit to 64-bit would cause many more incompatibilities at the binary level.

Thank you for reading. Do let me know if you want to see an article on some specific topic :)

No comments:

Post a Comment