[exim-dev] Numeric overflow in retry logic?

Top Page
Delete this message
Reply to this message
Author: Michael Haardt
Date:  
To: exim-dev
Subject: [exim-dev] Numeric overflow in retry logic?
Hello,

finally I compared the G and the H retry rules and I think that both
rules can easily cause numeric overflows if retry_interval_max is set
to larger values than 24h. The result would be a short retry interval
after a series of long intervals.

The first part of the patch moves retry_interval_max processing to
prevent overflows. Sorry about the code now being even less readable.

The H rule causes too random intervals for my taste. What I wanted was
a random number in an geometrically growing interval, but said interval
is not permanently stored, so effectively you got a random number.
The second part of the patch changes the algorithm to be 50% less random,
which looks way better to me. Factors of 1.5 or 2.0 are good.

Michael
----------------------------------------------------------------------
--- exim-4.60/src/retry.c.orig    2006-01-02 13:02:35.000000000 +0100
+++ exim-4.60/src/retry.c    2006-01-02 13:05:15.000000000 +0100
@@ -746,7 +746,11 @@
             int last_actual_gap = now - retry_record->last_try;
             int lastgap = (last_predicted_gap < last_actual_gap)?
               last_predicted_gap : last_actual_gap;
-            int next_gap = (lastgap * rule->p2)/1000;
+            /* Impose a global retry max */
+            if ((retry_interval_max*1000)/p2>lastgap)
+              next_gap = (lastgap * p2)/1000;
+            else
+              next_gap = retry_interval_max;
             if (rule->rule == 'G')
               {
               next_try = now + ((lastgap < rule->p1)? rule->p1 : next_gap);
@@ -755,16 +759,11 @@
               {
               next_try = now + rule->p1;
               if (next_gap > rule->p1)
-                next_try += random_number(next_gap - rule->p1);
+                next_try += random_number(next_gap - rule->p1)/2 + (next_gap - p1)/2;
               }
             }
           }


-        /* Impose a global retry max */
-
-        if (next_try - now > retry_interval_max)
-          next_try = now + retry_interval_max;
-
         /* If the new message length is greater than the previous one, we
         have to copy the record first. */