Ticket UUID: | 00655c867eabd57ac3acd93bffe2f93799c12c89 | |||
Title: | ClockGetdatefieldsObjCmd(): avoid signed integer overflow and platform-dependent behavior | |||
Type: | Patch | Version: | core-8-6-branch | |
Submitter: | chrstphrchvz | Created on: | 2023-05-09 21:05:40 | |
Subsystem: | 16. Commands A-H | Assigned To: | jan.nijtmans | |
Priority: | 5 Medium | Severity: | Minor | |
Status: | Closed | Last Modified: | 2023-09-21 11:15:36 | |
Resolution: | Fixed | Closed By: | jan.nijtmans | |
Closed on: | 2023-09-21 11:15:36 | |||
Description: |
clock-61.3 triggers an -fsanitize=signed-integer-overflow error: generic/tclClock.c:472:52: runtime error: signed integer overflow: 9223372036854775807 + 210866803200 cannot be represented in type 'long long' See attached patch. To avoid the overflow, I suggest dividing by SECONDS_PER_DAY first and then adding JULIAN_DAY_POSIX_EPOCH instead. The quotient also needs to be consistently rounded down, rather truncated towards 0 (GNU C and C99) or however a particular platform chooses (C89); otherwise incorrect results are produced for time values prior to the POSIX epoch. Not rounding down already produces incorrect results for time values prior to Julian day 0; the proposed clock-7.10 test currently fails with -210866803200 -210866889600 -1 -210866803201 0 -210866803200 0 0 0when integer division truncates toward 0. | |||
User Comments: |
jan.nijtmans added on 2023-09-21 11:15:36:
Thanks! Closing now. chrstphrchvz added on 2023-09-20 22:02:46: I neglected how clock add … days takes -timezone into consideration. Specifying -timezone :UTC to clock add … days avoids the failure on OPTS=static,msvcrt, although whether GetSystemTimeZone is correct or unexpectedly :localtime is beyond the scope of this test. -timezone should likely also be specified in the test’s other clock add usage for consistency. See attached patch. chrstphrchvz added on 2023-09-20 20:50:33: The exact cutoffs for localtime()/localtime_r() errors may depend on the platform epoch, but if struct tm is consistently defined, then I would think time values with years way outside of [1900+INT_MIN,1900+INT_MAX] will reliably cause an error. I will likely open other tickets about this. chrstphrchvz added on 2023-09-20 20:09:04: However, the conditions under which localtime()/localtime_r() encounters errors (e.g. EOVERFLOW) are platform-dependent. So a test which uses these functions may not be portable. chrstphrchvz added on 2023-09-20 16:57:37: I notice that ::tcl::clock::GetSystemTimeZone is returning :localtime when running tests for the OPTS=static,mscvrt configuration (rather than e.g. :America/Chicago), which causes ConvertUTCToLocal() to use ConvertUTCToLocalUsingC() instead of ConvertUTCToLocalUsingTable(). I am guessing this is not intentional. However I wonder if clock-7.10 should still work with :localtime, or be constrained to not run under :localtime. Either way, having a similar test which forces :localtime could be useful. jan.nijtmans added on 2023-09-20 15:54:28: Strange also, that all tests in 8.7 pass. Why does this fail in 8.6? chrstphrchvz added on 2023-09-20 15:12:23: I have reproduced this locally and will take a look. Note that without the change to tclClock.c the test still fails for the same reason. jan.nijtmans added on 2023-09-20 13:37:47:
The new testcase fails in a OPTS=static,msvcrt build in Visual Studio, passes in all other configurations. clock.test jan.nijtmans added on 2023-09-14 21:19:34: Fixed [ee677ecc84710dfd|here]. Many thanks! |
