[exim-cvs] Make integer values 64bit (bug 1171).

Forside
Slet denne besked
Besvar denne besked
Skribent: Exim Git Commits Mailing List
Dato:  
Til: exim-cvs
Emne: [exim-cvs] Make integer values 64bit (bug 1171).
Gitweb: http://git.exim.org/exim.git/commitdiff/aa7c82b2e34a4b0b341c6d05f81b4a349dcd06be
Commit:     aa7c82b2e34a4b0b341c6d05f81b4a349dcd06be
Parent:     3ff2360fd60b817623bee6e657e76b64423a7cec
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Mon Apr 23 22:47:58 2012 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sun May 13 17:15:11 2012 +0100


    Make integer values 64bit (bug 1171).
---
 src/src/expand.c             |  109 +++++++++++++++++++++---------------------
 src/src/functions.h          |    2 +-
 test/confs/0439              |    2 +-
 test/log/0439                |    6 +-
 test/paniclog/0439           |    6 +-
 test/scripts/0000-Basic/0002 |    3 +
 test/stderr/0439             |    6 +-
 test/stdout/0002             |    7 ++-
 8 files changed, 74 insertions(+), 67 deletions(-)


diff --git a/src/src/expand.c b/src/src/expand.c
index 22f7d9a..e847fb7 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -1781,7 +1781,7 @@ BOOL tempcond, combined_cond;
 BOOL *subcondptr;
 BOOL sub2_honour_dollar = TRUE;
 int i, rc, cond_type, roffset;
-int num[2];
+int64_t num[2];
 struct stat statbuf;
 uschar name[256];
 uschar *sub[4];
@@ -3069,14 +3069,14 @@ Returns:      on success: the value of the expression, with *error still NULL
               on failure: an undefined value, with *error = a message
 */


-static int eval_op_or(uschar **, BOOL, uschar **);
+static int64_t eval_op_or(uschar **, BOOL, uschar **);


-static int
+static int64_t
eval_expr(uschar **sptr, BOOL decimal, uschar **error, BOOL endket)
{
uschar *s = *sptr;
-int x = eval_op_or(&s, decimal, error);
+int64_t x = eval_op_or(&s, decimal, error);
if (*error == NULL)
{
if (endket)
@@ -3093,18 +3093,18 @@ return x;
}


-static int
+static int64_t
 eval_number(uschar **sptr, BOOL decimal, uschar **error)
 {
 register int c;
-int n;
+int64_t n;
 uschar *s = *sptr;
 while (isspace(*s)) s++;
 c = *s;
 if (isdigit(c))
   {
   int count;
-  (void)sscanf(CS s, (decimal? "%d%n" : "%i%n"), &n, &count);
+  (void)sscanf(CS s, (decimal? "%lld%n" : "%lli%n"), &n, &count);
   s += count;
   if (tolower(*s) == 'k') { n *= 1024; s++; }
     else if (tolower(*s) == 'm') { n *= 1024*1024; s++; }
@@ -3125,10 +3125,11 @@ return n;
 }



-static int eval_op_unary(uschar **sptr, BOOL decimal, uschar **error)
+static int64_t
+eval_op_unary(uschar **sptr, BOOL decimal, uschar **error)
{
uschar *s = *sptr;
-int x;
+int64_t x;
while (isspace(*s)) s++;
if (*s == '+' || *s == '-' || *s == '~')
{
@@ -3146,16 +3147,17 @@ return x;
}


-static int eval_op_mult(uschar **sptr, BOOL decimal, uschar **error)
+static int64_t
+eval_op_mult(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int x = eval_op_unary(&s, decimal, error);
+int64_t x = eval_op_unary(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '*' || *s == '/' || *s == '%')
     {
     int op = *s++;
-    int y = eval_op_unary(&s, decimal, error);
+    int64_t y = eval_op_unary(&s, decimal, error);
     if (*error != NULL) break;
     /* SIGFPE both on div/mod by zero and on INT_MIN / -1, which would give
      * a value of INT_MAX+1. Note that INT_MIN * -1 gives INT_MIN for me, which
@@ -3175,12 +3177,12 @@ if (*error == NULL)
      * can just let the other invalid results occur otherwise, as they have
      * until now.  For this one case, we can coerce.
      */
-    if (y == -1 && x == INT_MIN && op != '*')
+    if (y == -1 && x == LLONG_MIN && op != '*')
       {
       DEBUG(D_expand)
-        debug_printf("Integer exception dodging: %d%c-1 coerced to %d\n",
-            INT_MIN, op, INT_MAX);
-      x = INT_MAX;
+        debug_printf("Integer exception dodging: %lld%c-1 coerced to %lld\n",
+            LLONG_MIN, op, LLONG_MAX);
+      x = LLONG_MAX;
       continue;
       }
     if (op == '*')
@@ -3205,16 +3207,17 @@ return x;
 }



-static int eval_op_sum(uschar **sptr, BOOL decimal, uschar **error)
+static int64_t
+eval_op_sum(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int x = eval_op_mult(&s, decimal, error);
+int64_t x = eval_op_mult(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '+' || *s == '-')
     {
     int op = *s++;
-    int y = eval_op_mult(&s, decimal, error);
+    int64_t y = eval_op_mult(&s, decimal, error);
     if (*error != NULL) break;
     if (op == '+') x += y; else x -= y;
     }
@@ -3224,15 +3227,16 @@ return x;
 }



-static int eval_op_shift(uschar **sptr, BOOL decimal, uschar **error)
+static int64_t
+eval_op_shift(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int x = eval_op_sum(&s, decimal, error);
+int64_t x = eval_op_sum(&s, decimal, error);
 if (*error == NULL)
   {
   while ((*s == '<' || *s == '>') && s[1] == s[0])
     {
-    int y;
+    int64_t y;
     int op = *s++;
     s++;
     y = eval_op_sum(&s, decimal, error);
@@ -3245,15 +3249,16 @@ return x;
 }



-static int eval_op_and(uschar **sptr, BOOL decimal, uschar **error)
+static int64_t
+eval_op_and(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int x = eval_op_shift(&s, decimal, error);
+int64_t x = eval_op_shift(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '&')
     {
-    int y;
+    int64_t y;
     s++;
     y = eval_op_shift(&s, decimal, error);
     if (*error != NULL) break;
@@ -3265,15 +3270,16 @@ return x;
 }



-static int eval_op_xor(uschar **sptr, BOOL decimal, uschar **error)
+static int64_t
+eval_op_xor(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int x = eval_op_and(&s, decimal, error);
+int64_t x = eval_op_and(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '^')
     {
-    int y;
+    int64_t y;
     s++;
     y = eval_op_and(&s, decimal, error);
     if (*error != NULL) break;
@@ -3285,15 +3291,16 @@ return x;
 }



-static int eval_op_or(uschar **sptr, BOOL decimal, uschar **error)
+static int64_t
+eval_op_or(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int x = eval_op_xor(&s, decimal, error);
+int64_t x = eval_op_xor(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '|')
     {
-    int y;
+    int64_t y;
     s++;
     y = eval_op_xor(&s, decimal, error);
     if (*error != NULL) break;
@@ -5693,7 +5700,7 @@ while (*s != 0)
         {
         uschar *save_sub = sub;
         uschar *error = NULL;
-        int n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
+        int64_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
         if (error != NULL)
           {
           expand_string_message = string_sprintf("error in expression "
@@ -5701,7 +5708,7 @@ while (*s != 0)
               save_sub);
           goto EXPAND_FAILED;
           }
-        sprintf(CS var_buffer, "%d", n);
+        sprintf(CS var_buffer, "%lld", n);
         yield = string_cat(yield, &size, &ptr, var_buffer, Ustrlen(var_buffer));
         continue;
         }
@@ -5906,13 +5913,13 @@ while (*s != 0)


       case EOP_RANDINT:
         {
-        int max;
+        int64_t max;
         uschar *s;


         max = expand_string_integer(sub, TRUE);
         if (expand_string_message != NULL)
           goto EXPAND_FAILED;
-        s = string_sprintf("%d", pseudo_random_number(max));
+        s = string_sprintf("%d", pseudo_random_number((int)max));
         yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
         continue;
         }
@@ -6103,10 +6110,10 @@ Returns:  the integer value, or
           expand_string_message is set NULL for an OK integer
 */


-int
+int64_t
 expand_string_integer(uschar *string, BOOL isplus)
 {
-long int value;
+int64_t value;
 uschar *s = expand_string(string);
 uschar *msg = US"invalid integer \"%s\"";
 uschar *endptr;
@@ -6138,7 +6145,7 @@ if (isspace(*s))
     }
   }


-value = strtol(CS s, CSS &endptr, 10);
+value = strtoll(CS s, CSS &endptr, 10);

 if (endptr == s)
   {
@@ -6150,24 +6157,18 @@ else if (value < 0 && isplus)
   }
 else
   {
-  /* Ensure we can cast this down to an int */
-  if (value > INT_MAX  || value < INT_MIN) errno = ERANGE;
-
-  if (errno != ERANGE)
+  if (tolower(*endptr) == 'k')
     {
-    if (tolower(*endptr) == 'k')
-      {
-      if (value > INT_MAX/1024 || value < INT_MIN/1024) errno = ERANGE;
-        else value *= 1024;
-      endptr++;
-      }
+    if (value > LLONG_MAX/1024 || value < LLONG_MIN/1024) errno = ERANGE;
+      else value *= 1024;
+    endptr++;
+    }
     else if (tolower(*endptr) == 'm')
-      {
-      if (value > INT_MAX/(1024*1024) || value < INT_MIN/(1024*1024))
-        errno = ERANGE;
-      else value *= 1024*1024;
-      endptr++;
-      }
+    {
+    if (value > LLONG_MAX/(1024*1024) || value < LLONG_MIN/(1024*1024))
+      errno = ERANGE;
+    else value *= 1024*1024;
+    endptr++;
     }
   if (errno == ERANGE)
     msg = US"absolute value of integer \"%s\" is too large (overflow)";
diff --git a/src/src/functions.h b/src/src/functions.h
index 2202352..2ed9593 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -114,7 +114,7 @@ extern void    exim_wait_tick(struct timeval *, int);
 extern BOOL    expand_check_condition(uschar *, uschar *, uschar *);
 extern uschar *expand_string(uschar *);
 extern uschar *expand_string_copy(uschar *);
-extern int     expand_string_integer(uschar *, BOOL);
+extern int64_t expand_string_integer(uschar *, BOOL);


 extern int     filter_interpret(uschar *, int, address_item **, uschar **);
 extern BOOL    filter_personal(string_item *, BOOL);
diff --git a/test/confs/0439 b/test/confs/0439
index 67c51f4..1d79e65 100644
--- a/test/confs/0439
+++ b/test/confs/0439
@@ -12,6 +12,6 @@ gecos_name = CALLER_NAME


# ----- Main settings -----

-message_size_limit = 2048M
+message_size_limit = 8796093022208M

 # End
diff --git a/test/log/0439 b/test/log/0439
index 050f9f8..05245e7 100644
--- a/test/log/0439
+++ b/test/log/0439
@@ -1,4 +1,4 @@
-1999-03-02 09:44:33 invalid value for message_size_limit: absolute value of integer "2048M" is too large (overflow)
-1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "2048M" is too large (overflow)
+1999-03-02 09:44:33 invalid value for message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
+1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "2048M" is too large (overflow)
+1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
diff --git a/test/paniclog/0439 b/test/paniclog/0439
index 0cbb805..9b990fc 100644
--- a/test/paniclog/0439
+++ b/test/paniclog/0439
@@ -1,3 +1,3 @@
-1999-03-02 09:44:33 invalid value for message_size_limit: absolute value of integer "2048M" is too large (overflow)
-1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "2048M" is too large (overflow)
-1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "2048M" is too large (overflow)
+1999-03-02 09:44:33 invalid value for message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
+1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
+1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
diff --git a/test/scripts/0000-Basic/0002 b/test/scripts/0000-Basic/0002
index 01ba6d9..f87251e 100644
--- a/test/scripts/0000-Basic/0002
+++ b/test/scripts/0000-Basic/0002
@@ -239,9 +239,12 @@ md5:    ${if eq {1}{2}{${md5:invalid}}{NO}}
 mask:   ${if eq {1}{2}{${mask:invalid}}{NO}}


# Numeric overflow
+# >32b should work, >64b not

 4096M      ${if >{1}{4096M}{y}{n}}
 4096000000 ${if >{1}{4096000000}{y}{n}}
+4611686018427387904  ${if >{1}{4611686018427387904} {y}{n}}
+46116860184273879040 ${if >{1}{46116860184273879040}{y}{n}}


# Conditions

diff --git a/test/stderr/0439 b/test/stderr/0439
index ba7af58..18974ef 100644
--- a/test/stderr/0439
+++ b/test/stderr/0439
@@ -1,5 +1,5 @@
-1999-03-02 09:44:33 invalid value for message_size_limit: absolute value of integer "2048M" is too large (overflow)
-1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "2048M" is too large (overflow)
+1999-03-02 09:44:33 invalid value for message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
+1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)

******** SERVER ********
-1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "2048M" is too large (overflow)
+1999-03-02 09:44:33 invalid message_size_limit: absolute value of integer "8796093022208M" is too large (overflow)
diff --git a/test/stdout/0002 b/test/stdout/0002
index e209ada..c009fbd 100644
--- a/test/stdout/0002
+++ b/test/stdout/0002
@@ -221,9 +221,12 @@
> mask: NO
>
> # Numeric overflow

+> # >32b should work, >64b not
>

-> Failed: absolute value of integer "4096M" is too large (overflow)
-> Failed: absolute value of integer "4096000000" is too large (overflow)
+> 4096M      y
+> 4096000000 y
+> 4611686018427387904  y
+> Failed: absolute value of integer "46116860184273879040" is too large (overflow)

>
> # Conditions
>