4

The BSON Timestamp type, documented here https://www.mongodb.com/docs/manual/reference/bson-types/, includes a 32-bit time_t field. Does anyone know whether this field is signed or unsigned? If signed, it will roll over on January 19, 2038 (the Y2038 issue). If unsigned, it will not roll over until 2106.

The specific text in question is: "the most significant 32 bits are a time_t value (seconds since the Unix epoch)"

I understand that BSON Timestamp is intended for internal use only, as noted in the documentation. However, a signed time_t in this field could cause internal rollover issues in MongoDB itself or impact any applications that happen to use this type directly.

ObjectId also has undefined signedness, as per this text: "A 4-byte timestamp, representing the ObjectId's creation, measured in seconds since the Unix epoch."

0

2 Answers 2

2

The timestamp structure doesn't define whether that 32-bit timestamp value is signed or not.

In a quick test, the constructor in the shell will not accept a negative value, but the epoch portions of the timestamp can return a negative timestamp unless unsigned is requested:

test> let t = Timestamp(-10000,1)
BSONError: Timestamp constructed from { t, i } must provide a positive t
test> let t = Timestamp(Math.pow(2,32)+1,1)
BSONError: Timestamp constructed from { t, i } must provide t equal or less than uint32 max
test> let t = Timestamp(Math.pow(2,32)-1,1)

test> new Date(t.getHighBits()*1000)
ISODate('1969-12-31T23:59:59.000Z')
test> new Date(t.getHighBitsUnsigned()*1000)
ISODate('2106-02-07T06:28:15.000Z')
Sign up to request clarification or add additional context in comments.

Comments

2

Looking at the source code for Timestamp, these constructors use two unsigned 32-bit longs to represent a Timestmap. The first of those (most-significant 32-its) is seconds since the Epoch. So, for now, it will overflow in the year 2106, rather than 2038.

Also, the rest of that file only has unsigned long long for all operations.

/**
 * Constructor that builds a Timestamp from a 64-bit unsigned integer by using
 * the high-order 4 bytes of "v" for the "secs" field and the low-order 4 bytes for the "i"
 * field.
 */
explicit Timestamp(unsigned long long val) : Timestamp(val >> 32, val) {}

Timestamp(Seconds s, unsigned increment) : Timestamp(s.count(), increment) {}

Timestamp(unsigned a, unsigned b) : i(b), secs(a) {}

However, there are some open and as-yet-unresolved bugs related to Y2038, which the team now has 13 years to fix. Example: Replication fails if server date exceeds January 19th, 2038

Also worth noting, for the BSON Date type that we're supposed to use:

BSON Date is a 64-bit integer that represents the number of milliseconds since the Unix epoch (Jan 1, 1970). This results in a representable date range of about 290 million years into the past and future.

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.