realm / realm-core

Core database component for the Realm Mobile Database SDKs
https://realm.io
Apache License 2.0
1.02k stars 158 forks source link

Timestamp serialization fails on large deltas from epoch #6892

Closed nielsenko closed 1 month ago

nielsenko commented 1 year ago

Realm represent timestamps as 64 bit seconds offset from epoch (1970) and a 32 bit nano-seconds component. Hence realm can represent offsets from epoch up to (1 << 63)s / 86400s/day = 9223372036854689408 days.

The buffer used to serialize is just 32 bytes. From timestamp.hpp:202:

    char buffer[32];
    out << d.to_string(buffer);

The largest year representable with a realm timestamp is roughly (1 <<63)s / 86400s/day / 365day/years = 292471208677years. Hence we need 13 (12 + 1 for sign) bytes just for the years. Then 14 for %m-%d %H:%M:%S and another 10 for the nanoseconds and the preceding . which is 37 altogether.

A true iso8601 serialized utc timestamp also has a Z at the end and T separating date from time instead of a space.

Core version: 13.17.2

nielsenko commented 1 year ago

@rorbech & @cmelchior I believe the Java SDK is actually impacted by this. For Dart it is just some test cases that fails.

rorbech commented 4 months ago

This also fails for Kotlin's RealmInstant.MIN.

Callint:

realm::Timestamp::to_string(std::__ndk1::array<…> &) const serializer.cpp:128

With:

this = {const realm::Timestamp *} 0x72a7d14148 
 m_seconds = {int64_t} -9223372036854775808
 m_nanoseconds = {int32_t} -999999999
 m_is_null = {bool} false

Will generate this string:

"-188\xde-01-5: 15:30:07.000000001"
rorbech commented 1 month ago

Serialization of Kotlin's RealmInstant.MIN is fixed by https://github.com/realm/realm-core/pull/7934.

nielsenko commented 1 month ago

I guess I can close my PR then