From f59a26a7c8e592e030fd55bc5e1dc02789dc7bbe Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 14 Sep 2023 21:17:21 +0000 Subject: Fix [00655c867e]: ClockGetdatefieldsObjCmd(): avoid signed integer overflow and platform-dependent behavior --- generic/tclClock.c | 8 +++++--- tests/clock.test | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index d379762..194cfb3 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -466,11 +466,13 @@ ClockGetdatefieldsObjCmd( } /* - * Extract Julian day. + * Extract Julian day. Always round the quotient down by subtracting 1 + * when the remainder is negative (i.e. if the quotient was rounded up). */ - fields.julianDay = (int) ((fields.localSeconds + JULIAN_SEC_POSIX_EPOCH) - / SECONDS_PER_DAY); + fields.julianDay = (int) ((fields.localSeconds / SECONDS_PER_DAY) - + ((fields.localSeconds % SECONDS_PER_DAY) < 0) + + JULIAN_DAY_POSIX_EPOCH); /* * Convert to Julian or Gregorian calendar. diff --git a/tests/clock.test b/tests/clock.test index 587828f..4b12d5c 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -18600,6 +18600,20 @@ test clock-7.9 {Julian Day, two values} { clock scan {2440588 2440589} -format {%J %J} -gmt true } 86400 +test clock-7.10 {Julian Day, negative amount} { + # Note: %J does not accept negative input; + # add negative amounts to Julian day 0 instead + set s0 [clock scan 0 -format %J -gmt true] + set J0 [scan [clock format $s0 -format %J -gmt true] %lld] + set s0m1d [clock add $s0 -1 days] + set s0m24h [clock add $s0 -24 hours] + set J0m24h [scan [clock format $s0m24h -format %J -gmt true] %lld] + set s0m1s [clock add $s0 -1 seconds] + set J0m1s [scan [clock format $s0m1s -format %J -gmt true] %lld] + list $s0m1d $s0m24h $J0m24h $s0m1s $J0m1s $s0 $J0 \ + [::tcl::mathop::== $s0m1d $s0m24h] [::tcl::mathop::== $J0m24h $J0m1s] +} [list -210866889600 -210866889600 -1 -210866803201 -1 -210866803200 0 1 1] + # BEGIN testcases8 # Test parsing of ccyymmdd -- cgit v0.12