-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
time.h: fix integer overflow in MsToAbsoluteTimespec() on 32-bit architectures #1042
Conversation
✅ Integration test succeeded!Requested by @dconeybe on commit ed0d970 |
app/src/time.h
Outdated
(milliseconds * internal::kNanosecondsPerMillisecond); | ||
|
||
t.tv_sec = nanoseconds / internal::kNanosecondsPerSecond; | ||
t.tv_nsec = nanoseconds - (t.tv_sec * internal::kNanosecondsPerSecond); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to not use % ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. Done.
|
||
TEST(TimeTests, MsToAbsoluteTimespecTest) { | ||
const timespec t1 = firebase::internal::MsToAbsoluteTimespec(0); | ||
const timespec t2 = firebase::internal::MsToAbsoluteTimespec(10000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these value test for previous overflow scenarios?
If so a comment saying that this tests for overlfow on 32 bit systems would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as the test gets run on a 32-bit architecture it will detect the overflow. I'm not sure how our GitHub Actions are set up and if they trigger these tests on 32-bit platforms. I've opened a temporary PR #1043 to see if any of the GitHub Actions fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've also added this inline comment to time_test.cc:
This test verifies the fix for the old integer overflow bug on 32-bit architectures: #1042.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've verified the fix using GitHub Actions in #1043
…that MsToAbsoluteTimespecTest verifies
This PR fixes a long-standing bug in
MsToAbsoluteTimespec(int milliseconds)
which would result in an integer overflow if invoked with a sufficiently-large "milliseconds". The bug manifested on 32-bit architectures because thetv_sec
andtv_nsec
members oftimespec
are 4 bytes each (32 bits), where on 64-bit architectures they are 8 bytes each (64 bits), and did not suffer from the overflow.The problem was that in
MsToAbsoluteTimespec(int milliseconds)
it would add the given milliseconds, after converting to nanoseconds, to thetv_nsec
member, and then call a helper function to normalize the values; however, when being invoked with amilliseconds
value of10000
(10 seconds) this would causetv_nsec
to overflow and wrap around to a negative value. When this malformedtimespec
was later specified tosem_timedwait()
inSemaphore::TimedWait()
it would cause the function call to fail immediately withEINVAL
.The fix in this PR is to instead do all of the math with an
int64_t
and then calculate thetv_sec
andtv_nsec
values from it. By doing all of the math with a 64-bit integer, no overflow occurs.This fix will also fix a bunch of Firestore's transaction tests which are currently failing on 32-bit architectures due to this bug when they call
Future::Await(10000)
.Here is one example of a testapp crash due to this bug on an x86 Android emulator. Here is the implementation of
MsToAbsoluteTimespec()
with the bug:firebase-cpp-sdk/app/src/time.h
Lines 89 to 95 in 05890ac
In this test, the
milliseconds
argument was10000
(10 seconds) and thetimespec t
had the following values after the following lines:You can see that
tv_nsec
is negative, which is invalid.