Commit 6aff0489 authored by George Kadianakis's avatar George Kadianakis
Browse files

Merge branch 'maint-0.4.6'

parents e71db3a4 167f3bc4
Loading
Loading
Loading
Loading

changes/bug40383

0 → 100644
+7 −0
Original line number Original line Diff line number Diff line
  o Minor bugfixes (timekeeping):
    - Calculate the time of day correctly on systems where the time_t
      type includes leap seconds. (This is not the case on most
      operating systems, but on those where it occurs, our tor_timegm
      function did not correctly invert the system's gmtime function,
      which could result in assertion failures when calculating
      voting schedules.)  Fixes bug 40383; bugfix on 0.2.0.3-alpha.
+1 −0
Original line number Original line Diff line number Diff line
@@ -806,6 +806,7 @@ AC_CHECK_FUNCS(
	strtoull \
	strtoull \
	sysconf \
	sysconf \
	sysctl \
	sysctl \
        timegm \
	truncate \
	truncate \
	uname \
	uname \
	usleep \
	usleep \
+33 −2
Original line number Original line Diff line number Diff line
@@ -13,6 +13,7 @@
 * and handles a larger variety of types.  It converts between different time
 * and handles a larger variety of types.  It converts between different time
 * formats, and encodes and decodes them from strings.
 * formats, and encodes and decodes them from strings.
 **/
 **/
#define TIME_FMT_PRIVATE


#include "lib/encoding/time_fmt.h"
#include "lib/encoding/time_fmt.h"
#include "lib/log/log.h"
#include "lib/log/log.h"
@@ -25,6 +26,7 @@


#include <string.h>
#include <string.h>
#include <time.h>
#include <time.h>
#include <errno.h>


#ifdef HAVE_SYS_TIME_H
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <sys/time.h>
@@ -92,8 +94,8 @@ static const int days_per_month[] =
/** Compute a time_t given a struct tm.  The result is given in UTC, and
/** Compute a time_t given a struct tm.  The result is given in UTC, and
 * does not account for leap seconds.  Return 0 on success, -1 on failure.
 * does not account for leap seconds.  Return 0 on success, -1 on failure.
 */
 */
int
ATTR_UNUSED STATIC int
tor_timegm(const struct tm *tm, time_t *time_out)
tor_timegm_impl(const struct tm *tm, time_t *time_out)
{
{
  /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
  /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
   * It's way more brute-force than fiddling with tzset().
   * It's way more brute-force than fiddling with tzset().
@@ -162,6 +164,35 @@ tor_timegm(const struct tm *tm, time_t *time_out)
  return 0;
  return 0;
}
}


/** Compute a time_t given a struct tm.  The result here should be an inverse
 * of the system's gmtime() function.  Return 0 on success, -1 on failure.
 */
int
tor_timegm(const struct tm *tm, time_t *time_out)
{
#ifdef HAVE_TIMEGM
  /* If the system gives us a timegm(), use it: if the system's time_t
   * includes leap seconds, then we can hope that its timegm() knows too.
   *
   * https://k5wiki.kerberos.org/wiki/Leap_second_handling says the in
   * general we can rely on any system with leap seconds also having a
   * timegm implementation.  Let's hope it's right!
   * */
  time_t result = timegm((struct tm *) tm);
  if (result == -1) {
    log_warn(LD_BUG, "timegm() could not convert time: %s", strerror(errno));
    *time_out = 0;
    return -1;
  } else {
    *time_out = result;
    return 0;
  }
#else
  /* The system doesn't have timegm; we'll have to use our own. */
  return tor_timegm_impl(tm, time_out);
#endif
}

/* strftime is locale-specific, so we need to replace those parts */
/* strftime is locale-specific, so we need to replace those parts */


/** A c-locale array of 3-letter names of weekdays, starting with Sun. */
/** A c-locale array of 3-letter names of weekdays, starting with Sun. */
+6 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,8 @@
#include <sys/types.h>
#include <sys/types.h>
#endif
#endif


#include "lib/testsupport/testsupport.h"

struct tm;
struct tm;
struct timeval;
struct timeval;


@@ -41,4 +43,8 @@ int parse_iso_time_nospace(const char *cp, time_t *t);
int parse_http_time(const char *buf, struct tm *tm);
int parse_http_time(const char *buf, struct tm *tm);
int format_time_interval(char *out, size_t out_len, long interval);
int format_time_interval(char *out, size_t out_len, long interval);


#ifdef TIME_FMT_PRIVATE
STATIC int tor_timegm_impl(const struct tm *tm, time_t *time_out);
#endif

#endif /* !defined(TOR_TIME_FMT_H) */
#endif /* !defined(TOR_TIME_FMT_H) */
+25 −1
Original line number Original line Diff line number Diff line
@@ -7,6 +7,7 @@
#define COMPAT_TIME_PRIVATE
#define COMPAT_TIME_PRIVATE
#define UTIL_MALLOC_PRIVATE
#define UTIL_MALLOC_PRIVATE
#define PROCESS_WIN32_PRIVATE
#define PROCESS_WIN32_PRIVATE
#define TIME_FMT_PRIVATE
#include "lib/testsupport/testsupport.h"
#include "lib/testsupport/testsupport.h"
#include "core/or/or.h"
#include "core/or/or.h"
#include "lib/buf/buffers.h"
#include "lib/buf/buffers.h"
@@ -111,7 +112,7 @@ static time_t
tor_timegm_wrapper(const struct tm *tm)
tor_timegm_wrapper(const struct tm *tm)
{
{
  time_t t;
  time_t t;
  if (tor_timegm(tm, &t) < 0)
  if (tor_timegm_impl(tm, &t) < 0)
    return -1;
    return -1;
  return t;
  return t;
}
}
@@ -1501,6 +1502,28 @@ test_util_parse_http_time(void *arg)
  teardown_capture_of_logs();
  teardown_capture_of_logs();
}
}


static void
test_util_timegm_real(void *arg)
{
  (void)arg;
  /* Get the real timegm again!  We're not testing our impl; we want the
   * one that will actually get called. */
#undef tor_timegm

  /* Now check: is timegm the real inverse of gmtime? */
  time_t now = time(NULL), time2=0;
  struct tm tm, *p;
  p = tor_gmtime_r(&now, &tm);
  tt_ptr_op(p, OP_NE, NULL);

  int r = tor_timegm(&tm, &time2);
  tt_int_op(r, OP_EQ, 0);
  tt_i64_op((int64_t) now, OP_EQ, (int64_t) time2);

 done:
  ;
}

static void
static void
test_util_config_line(void *arg)
test_util_config_line(void *arg)
{
{
@@ -7036,6 +7059,7 @@ struct testcase_t util_tests[] = {
  UTIL_TEST(monotonic_time_ratchet, TT_FORK),
  UTIL_TEST(monotonic_time_ratchet, TT_FORK),
  UTIL_TEST(monotonic_time_zero, 0),
  UTIL_TEST(monotonic_time_zero, 0),
  UTIL_TEST(monotonic_time_add_msec, 0),
  UTIL_TEST(monotonic_time_add_msec, 0),
  UTIL_TEST(timegm_real, 0),
  UTIL_TEST(htonll, 0),
  UTIL_TEST(htonll, 0),
  UTIL_TEST(get_unquoted_path, 0),
  UTIL_TEST(get_unquoted_path, 0),
  UTIL_TEST(map_anon, 0),
  UTIL_TEST(map_anon, 0),