This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] Avoid overflows in the windows __libcpp_steady_clock_now()
ClosedPublic

Authored by mstorsjo on Dec 17 2020, 5:50 AM.

Details

Summary

As freq.QuadValue can be in the range of 10000000 to 19200000, the multiplication before division makes the calculation overflow and wrap to negative values every 16-30 minutes.

Instead count the whole seconds separately before adding the scaled fractional seconds.

Add a testcase for steady_clock to check that the values returned for now() compare as bigger than the zero time origin; this corresponds to a testcase in Qt [1] [2] (that failed spuriously due to this).

[1] https://bugreports.qt.io/browse/QTBUG-89539
[2] https://code.qt.io/cgit/qt/qtbase.git/tree/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp?id=f8de5e54022b8b7471131b7ad55c83b69b2684c0#n569

Diff Detail

Event Timeline

mstorsjo requested review of this revision.Dec 17 2020, 5:50 AM
mstorsjo created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptDec 17 2020, 5:50 AM
Herald added 1 blocking reviewer(s): Restricted Project. · View Herald Transcript
amccarth accepted this revision.Dec 17 2020, 9:08 AM

This looks correct and straightforward, so LGTM.

There's probably a "clever" solution involving finding the greatest common divisor (once) of nano::den and freq.QuadPart. That would depend on there being a significant common divisor (which I assume is probably true, but not guaranteed). I think the straightforward solution in this patch is better.

libcxx/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp
28

I don't know what the libcxx style guidelines say, but my inclination would be to add a comment explaining this assertion. Since the original bug would only occasionally be caught by this assertion, somebody who encounters it might need a hint to look for arithmetic overflows.

ldionne accepted this revision.Jan 12 2021, 7:42 AM
ldionne added a subscriber: ldionne.

LGTM with or without the test comment.

libcxx/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp
28

I think a short comment doesn't hurt. Ideally something that isn't strictly related to the bug, like // make sure t2 didn't wrap around or something along those lines.

This revision is now accepted and ready to land.Jan 12 2021, 7:42 AM