From: Juergen Perlinger Date: Fri, 8 May 2015 21:35:42 +0000 (+0200) Subject: * [Bug 2745] ntpd -x steps clock on leap second X-Git-Tag: NTP_4_2_8P3_RC1~2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=90602b053ade841cf2703a2ad6b8c84b0bfc7957;p=thirdparty%2Fntp.git * [Bug 2745] ntpd -x steps clock on leap second Fixed an initial-value problem that caused misbehaviour in absence of any leapsecond information. bk: 554d2c2eJdwiC4Mn2mal_ZCFPG9RUg --- diff --git a/ChangeLog b/ChangeLog index 15bfe2f2b..13e05e7dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,8 @@ of 'limited'. * [Bug 2650] fix includefile processing. * [Bug 2745] ntpd -x steps clock on leap second + Fixed an initial-value problem that caused misbehaviour in absence of + any leapsecond information. Do leap second stepping only of the step adjustment is beyond the proper jump distance limit and step correction is allowed at all. * [Bug 2776] Improve ntpq's 'help keytype'. diff --git a/ntpd/ntp_leapsec.c b/ntpd/ntp_leapsec.c index eeef89f3c..09185b5cc 100644 --- a/ntpd/ntp_leapsec.c +++ b/ntpd/ntp_leapsec.c @@ -107,8 +107,17 @@ leapsec_get_table( leap_table_t *p1, *p2; p1 = _lptr; - p1 = &_ltab[p1 == &_ltab[1]]; - p2 = &_ltab[p1 == &_ltab[0]]; + if (p1 == &_ltab[0]) { + p2 = &_ltab[1]; + } else if (p1 == &_ltab[1]) { + p2 = &_ltab[0]; + } else { + p1 = &_ltab[0]; + p2 = &_ltab[1]; + reset_times(p1); + reset_times(p2); + _lptr = p1; + } if (alternate) { memcpy(p2, p1, sizeof(leap_table_t)); p1 = p2; @@ -282,13 +291,21 @@ leapsec_query( pt = leapsec_get_table(FALSE); memset(qr, 0, sizeof(leap_result_t)); +#if 0 + printf("ebase=%s dtime=%s\n", lstostr(&pt->head.ebase), lstostr(&pt->head.dtime)); + if (ucmpv64(&pt->head.dtime, &pt->head.ebase) <= 0) { + /* Initial state and empty table. Fix it. */ + reload_limits(pt, &ts64); + printf("\n\n PRESET INITAL CONDITION\n\n\n"); + } else +#endif if (ucmpv64(&ts64, &pt->head.ebase) < 0) { /* Most likely after leap frame reset. Could also be a * backstep of the system clock. Anyway, get the new * leap era frame. */ reload_limits(pt, &ts64); - } else if (ucmpv64(&ts64, &pt->head.dtime) >= 0) { + } else if (ucmpv64(&ts64, &pt->head.dtime) >= 0) { /* Boundary crossed in forward direction. This might * indicate a leap transition, so we prepare for that * case. @@ -1005,6 +1022,15 @@ static char * lstostr( return buf; } +/* reset the global state for unit tests */ +void +leapsec_ut_pristine(void) +{ + memset(_ltab, 0, sizeof(_ltab)); + _lptr = NULL; + _electric = 0; +} + /* -*- that's all folks! -*- */ diff --git a/ntpd/ntp_leapsec.h b/ntpd/ntp_leapsec.h index 75edcc460..c9af1ea45 100644 --- a/ntpd/ntp_leapsec.h +++ b/ntpd/ntp_leapsec.h @@ -215,4 +215,7 @@ extern int/*BOOL*/ leapsec_query(leap_result_t *qr, uint32_t ntpts, */ extern int/*BOOL*/ leapsec_frame(leap_result_t *qr); +/* reset global state for unit tests */ +extern void leapsec_ut_pristine(void); + #endif /* !defined(NTP_LEAPSEC_H) */ diff --git a/tests/ntpd/leapsec.cpp b/tests/ntpd/leapsec.cpp index 47eb06956..011595154 100644 --- a/tests/ntpd/leapsec.cpp +++ b/tests/ntpd/leapsec.cpp @@ -292,7 +292,7 @@ void leapsecTest::SetUp() { ntpcal_set_timefunc(timefunc); settime(1970, 1, 1, 0, 0, 0); - leapsec_electric(1); + leapsec_ut_pristine(); } void leapsecTest::TearDown() @@ -429,6 +429,18 @@ TEST_F(leapsecTest, loadFileTTL) { EXPECT_EQ(-1, rc); } +// ---------------------------------------------------------------------- +// test query in pristine state (bug#2745 misbehaviour) +TEST_F(leapsecTest, lsQueryPristineState) { + int rc; + leap_result_t qr; + + rc = leapsec_query(&qr, lsec2012, NULL); + EXPECT_EQ(FALSE, rc); + EXPECT_EQ(0, qr.warped ); + EXPECT_EQ(LSPROX_NOWARN, qr.proximity); +} + // ---------------------------------------------------------------------- // ad-hoc jump: leap second at 2009.01.01 -60days TEST_F(leapsecTest, ls2009faraway) { @@ -641,6 +653,7 @@ TEST_F(leapsecTest, ls2009seqInsElectric) { rc = setup_load_table(leap1); EXPECT_EQ(1, rc); leapsec_electric(1); + EXPECT_EQ(1, leapsec_electric(-1)); rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL); EXPECT_EQ(FALSE, rc); @@ -682,7 +695,7 @@ TEST_F(leapsecTest, ls2009seqInsDumb) { rc = setup_load_table(leap1); EXPECT_EQ(1, rc); - leapsec_electric(0); + EXPECT_EQ(0, leapsec_electric(-1)); rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL); EXPECT_EQ(FALSE, rc); @@ -731,6 +744,7 @@ TEST_F(leapsecTest, ls2009seqDelElectric) { rc = setup_load_table(leap3); EXPECT_EQ(1, rc); leapsec_electric(1); + EXPECT_EQ(1, leapsec_electric(-1)); rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL); EXPECT_EQ(FALSE, rc); @@ -772,7 +786,7 @@ TEST_F(leapsecTest, ls2009seqDelDumb) { rc = setup_load_table(leap3); EXPECT_EQ(1, rc); - leapsec_electric(0); + EXPECT_EQ(0, leapsec_electric(-1)); rc = leapsec_query(&qr, lsec2009 - 60*SECSPERDAY, NULL); EXPECT_EQ(FALSE, rc); @@ -814,6 +828,8 @@ TEST_F(leapsecTest, ls2012seqInsElectric) { rc = setup_load_table(leap1); EXPECT_EQ(1, rc); + leapsec_electric(1); + EXPECT_EQ(1, leapsec_electric(-1)); rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL); EXPECT_EQ(FALSE, rc); @@ -853,12 +869,9 @@ TEST_F(leapsecTest, ls2012seqInsDumb) { int rc; leap_result_t qr; - leapsec_electric(0); - EXPECT_EQ(0, leapsec_electric(-1)); - EXPECT_EQ(0, leapsec_electric(-1)); - rc = setup_load_table(leap1); EXPECT_EQ(1, rc); + EXPECT_EQ(0, leapsec_electric(-1)); rc = leapsec_query(&qr, lsec2012 - 60*SECSPERDAY, NULL); EXPECT_EQ(FALSE, rc); @@ -909,10 +922,8 @@ TEST_F(leapsecTest, lsEmptyTableDumb) { const uint32_t t0 (lsec2012 - 10); const uint32_t tE (lsec2012 + 10); - leapsec_electric(0); EXPECT_EQ(0, leapsec_electric(-1)); - leapsec_clear(leapsec_get_table(FALSE)); for (uint32_t t = t0; t != tE; ++t) { rc = leapsec_query(&qr, t, &pivot); EXPECT_EQ(FALSE, rc); @@ -934,7 +945,6 @@ TEST_F(leapsecTest, lsEmptyTableElectric) { const uint32_t t0 (lsec2012 - 10); const uint32_t tE (lsec2012 + 10); - leapsec_clear(leapsec_get_table(FALSE)); for (time_t t = t0; t != tE; ++t) { rc = leapsec_query(&qr, t, &pivot); EXPECT_EQ(FALSE, rc);