]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: time-util: Fix timeval_cmp_margin() to correctly handle a margin crossing the...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 6 Feb 2018 14:50:19 +0000 (15:50 +0100)
committerMartti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
Wed, 7 Feb 2018 08:19:41 +0000 (10:19 +0200)
The timeval_cmp_margin() function incorrectly assumed that the margin is
irrelevent when the tv_sec values are different.

src/lib/test-time-util.c
src/lib/time-util.c

index eff77bdddb6eb67ced5801af40b2f40f203d6c07..e0c7a29f61302ffa1a6e256b45771f92661ee12a 100644 (file)
@@ -54,6 +54,143 @@ static void test_timeval_cmp(void)
        test_end();
 }
 
+static void test_timeval_cmp_margin(void)
+{
+       static const struct {
+               struct timeval tv1, tv2;
+               unsigned int margin;
+               int output;
+       } tests[] = {
+               {
+                       .tv1 = { 0, 0 },
+                       .tv2 = { 0, 0 },
+                       .output = 0,
+               },{
+                       .tv1 = { INT_MAX, 999999 },
+                       .tv2 = { INT_MAX, 999999 },
+                       .output = 0,
+
+               },{
+                       .tv1 = { 0, 0 },
+                       .tv2 = { 0, 1 },
+                       .output = -1,
+               },{
+                       .tv1 = { 0, 0 },
+                       .tv2 = { 1, 0 },
+                       .output = -1,
+               },{
+                       .tv1 = { 0, 999999 },
+                       .tv2 = { 1, 0 },
+                       .output = -1,
+               },{
+                       .tv1 = { 1, 0 },
+                       .tv2 = { 1, 1 },
+                       .output = -1,
+               },{
+                       .tv1 = { -INT_MAX, 0 },
+                       .tv2 = { INT_MAX, 0 },
+                       .output = -1,
+               },{
+                       .tv1 = { 0, 999999 },
+                       .tv2 = { 1, 0 },
+                       .margin = 1,
+                       .output = 0,
+               },{
+                       .tv1 = { 1, 0 },
+                       .tv2 = { 1, 1 },
+                       .margin = 1,
+                       .output = 0,
+               },{
+                       .tv1 = { 0, 999998 },
+                       .tv2 = { 1, 0 },
+                       .margin = 1,
+                       .output = -1,
+               },{
+                       .tv1 = { 1, 0 },
+                       .tv2 = { 1, 2 },
+                       .margin = 1,
+                       .output = -1,
+               },{
+                       .tv1 = { 0, 998000 },
+                       .tv2 = { 1, 0 },
+                       .margin = 2000,
+                       .output = 0,
+               },{
+                       .tv1 = { 1, 0 },
+                       .tv2 = { 1, 2000 },
+                       .margin = 2000,
+                       .output = 0,
+               },{
+                       .tv1 = { 0, 997999 },
+                       .tv2 = { 1, 0 },
+                       .margin = 2000,
+                       .output = -1,
+               },{
+                       .tv1 = { 1, 0 },
+                       .tv2 = { 1, 2001 },
+                       .margin = 2000,
+                       .output = -1,
+               },{
+                       .tv1 = { 0, 1 },
+                       .tv2 = { 1, 0 },
+                       .margin = 999999,
+                       .output = 0,
+               },{
+                       .tv1 = { 1, 0 },
+                       .tv2 = { 1, 999999 },
+                       .margin = 999999,
+                       .output = 0,
+               },{
+                       .tv1 = { 0, 0 },
+                       .tv2 = { 1, 0 },
+                       .margin = 999999,
+                       .output = -1,
+               },{
+                       .tv1 = { 1, 0 },
+                       .tv2 = { 2, 0 },
+                       .margin = 999999,
+                       .output = -1,
+               },{
+                       .tv1 = { 10, 0 },
+                       .tv2 = { 11, 500000 },
+                       .margin = 1500000,
+                       .output = 0,
+               },{
+                       .tv1 = { 8, 500000 },
+                       .tv2 = { 10, 0 },
+                       .margin = 1500000,
+                       .output = 0,
+               },{
+                       .tv1 = { 10, 0 },
+                       .tv2 = { 11, 500001 },
+                       .margin = 1500000,
+                       .output = -1,
+               },{
+                       .tv1 = { 8, 499999 },
+                       .tv2 = { 10, 0 },
+                       .margin = 1500000,
+                       .output = -1,
+               },{
+                       .tv1 = { 1517925358, 999989 },
+                       .tv2 = { 1517925359, 753 },
+                       .margin = 2000,
+                       .output = 0,
+               }
+       };
+       unsigned int i;
+
+       test_begin("timeval_cmp_margin()");
+       for (i = 0; i < N_ELEMENTS(tests); i++) {
+               const struct timeval *tv1 = &tests[i].tv1, *tv2 = &tests[i].tv2;
+               unsigned int margin = tests[i].margin;
+               int output = tests[i].output;
+
+               test_assert(timeval_cmp_margin(tv1, tv2, margin) == output);
+               test_assert(timeval_cmp_margin(tv2, tv1, margin) == -output);
+       }
+       test_end();
+}
+
 static void test_timeval_diff(void)
 {
        static struct timeval input[] = {
@@ -201,6 +338,7 @@ static void test_strftime_fixed(void)
 void test_time_util(void)
 {
        test_timeval_cmp();
+       test_timeval_cmp_margin();
        test_timeval_diff();
        test_time_to_local_day_start();
        test_strftime_now();
index c38ab50f9467d9b4395b65b9d30dfb7bab398330..31eaf71b2e073be4a6a53e720d581a5aeaa28ff0 100644 (file)
@@ -23,16 +23,31 @@ int timeval_cmp(const struct timeval *tv1, const struct timeval *tv2)
 int timeval_cmp_margin(const struct timeval *tv1, const struct timeval *tv2,
        unsigned int usec_margin)
 {
-       if (tv1->tv_sec < tv2->tv_sec)
-               return -1;
-       if (tv1->tv_sec > tv2->tv_sec)
-               return 1;
-
-       if ((tv2->tv_usec - tv1->tv_usec) > (int)usec_margin)
-               return -1;
-       if ((tv1->tv_usec - tv2->tv_usec) > (int)usec_margin)
-               return 1;
-       return 0;
+       unsigned long long usecs_diff;
+       int sec_margin, ret;
+
+       if (tv1->tv_sec < tv2->tv_sec) {
+               sec_margin = ((int)usec_margin / 1000000) + 1;
+               if ((tv2->tv_sec - tv1->tv_sec) > sec_margin)
+                       return -1;
+               usecs_diff = (tv2->tv_sec - tv1->tv_sec) * 1000000ULL +
+                       (tv2->tv_usec - tv1->tv_usec);
+               ret = -1;
+       } else if (tv1->tv_sec > tv2->tv_sec) {
+               sec_margin = ((int)usec_margin / 1000000) + 1;
+               if ((tv1->tv_sec - tv2->tv_sec) > sec_margin)
+                       return 1;
+               usecs_diff = (tv1->tv_sec - tv2->tv_sec) * 1000000ULL +
+                       (tv1->tv_usec - tv2->tv_usec);
+               ret = 1;
+       } else if (tv1->tv_usec < tv2->tv_usec) {
+               usecs_diff = tv2->tv_usec - tv1->tv_usec;
+               ret = -1;
+       } else {
+               usecs_diff = tv1->tv_usec - tv2->tv_usec;
+               ret = 1;
+       }
+       return usecs_diff > usec_margin ? ret : 0;
 }
 
 int timeval_diff_msecs(const struct timeval *tv1, const struct timeval *tv2)