Patch 8.1.0990
Problem:    Floating point exception with "%= 0" and "/= 0".
Solution:   Avoid dividing by zero. (Dominique Pelle, closes #4058)
Files:      src/eval.c, src/testdir/test_vimscript.vim


*** ../vim-8.1.0989/src/eval.c  2019-02-20 22:04:28.823721308 +0100
--- src/eval.c  2019-03-02 11:55:06.947996350 +0100
***************
*** 253,258 ****
--- 253,291 ----
  /* for VIM_VERSION_ defines */
  #include "version.h"
  
+ /*
+  * Return "n1" divided by "n2", taking care of dividing by zero.
+  */
+       static varnumber_T
+ num_divide(varnumber_T n1, varnumber_T n2)
+ {
+     varnumber_T       result;
+ 
+     if (n2 == 0)      // give an error message?
+     {
+       if (n1 == 0)
+           result = VARNUM_MIN; // similar to NaN
+       else if (n1 < 0)
+           result = -VARNUM_MAX;
+       else
+           result = VARNUM_MAX;
+     }
+     else
+       result = n1 / n2;
+ 
+     return result;
+ }
+ 
+ /*
+  * Return "n1" modulus "n2", taking care of dividing by zero.
+  */
+       static varnumber_T
+ num_modulus(varnumber_T n1, varnumber_T n2)
+ {
+     // Give an error when n2 is 0?
+     return (n2 == 0) ? 0 : (n1 % n2);
+ }
+ 
  
  #if defined(EBCDIC) || defined(PROTO)
  /*
***************
*** 1758,1765 ****
                            case '+': n = numval + n; break;
                            case '-': n = numval - n; break;
                            case '*': n = numval * n; break;
!                           case '/': n = numval / n; break;
!                           case '%': n = numval % n; break;
                        }
                    }
                    else if (opt_type == 0 && stringval != NULL) // string
--- 1791,1798 ----
                            case '+': n = numval + n; break;
                            case '-': n = numval - n; break;
                            case '*': n = numval * n; break;
!                           case '/': n = (long)num_divide(numval, n); break;
!                           case '%': n = (long)num_modulus(numval, n); break;
                        }
                    }
                    else if (opt_type == 0 && stringval != NULL) // string
***************
*** 2538,2545 ****
                            case '+': n += tv_get_number(tv2); break;
                            case '-': n -= tv_get_number(tv2); break;
                            case '*': n *= tv_get_number(tv2); break;
!                           case '/': n /= tv_get_number(tv2); break;
!                           case '%': n %= tv_get_number(tv2); break;
                        }
                        clear_tv(tv1);
                        tv1->v_type = VAR_NUMBER;
--- 2571,2578 ----
                            case '+': n += tv_get_number(tv2); break;
                            case '-': n -= tv_get_number(tv2); break;
                            case '*': n *= tv_get_number(tv2); break;
!                           case '/': n = num_divide(n, tv_get_number(tv2)); 
break;
!                           case '%': n = num_modulus(n, tv_get_number(tv2)); 
break;
                        }
                        clear_tv(tv1);
                        tv1->v_type = VAR_NUMBER;
***************
*** 4113,4138 ****
                if (op == '*')
                    n1 = n1 * n2;
                else if (op == '/')
!               {
!                   if (n2 == 0)        /* give an error message? */
!                   {
!                       if (n1 == 0)
!                           n1 = VARNUM_MIN; /* similar to NaN */
!                       else if (n1 < 0)
!                           n1 = -VARNUM_MAX;
!                       else
!                           n1 = VARNUM_MAX;
!                   }
!                   else
!                       n1 = n1 / n2;
!               }
                else
!               {
!                   if (n2 == 0)        /* give an error message? */
!                       n1 = 0;
!                   else
!                       n1 = n1 % n2;
!               }
                rettv->v_type = VAR_NUMBER;
                rettv->vval.v_number = n1;
            }
--- 4146,4155 ----
                if (op == '*')
                    n1 = n1 * n2;
                else if (op == '/')
!                   n1 = num_divide(n1, n2);
                else
!                   n1 = num_modulus(n1, n2);
! 
                rettv->v_type = VAR_NUMBER;
                rettv->vval.v_number = n1;
            }
*** ../vim-8.1.0989/src/testdir/test_vimscript.vim      2019-02-12 
22:28:27.845232664 +0100
--- src/testdir/test_vimscript.vim      2019-03-02 11:49:05.814627589 +0100
***************
*** 21,27 ****
  "
  " Create a script that consists of the body of the function a:funcname.
  " Replace any ":return" by a ":finish", any argument variable by a global
! " variable, and and every ":call" by a ":source" for the next following 
argument
  " in the variable argument list.  This function is useful if similar tests are
  " to be made for a ":return" from a function call or a ":finish" in a script
  " file.
--- 21,27 ----
  "
  " Create a script that consists of the body of the function a:funcname.
  " Replace any ":return" by a ":finish", any argument variable by a global
! " variable, and every ":call" by a ":source" for the next following argument
  " in the variable argument list.  This function is useful if similar tests are
  " to be made for a ":return" from a function call or a ":finish" in a script
  " file.
***************
*** 1457,1462 ****
--- 1457,1499 ----
      let x .= 'n'
      call assert_equal('2n', x)
  
+     " Test special cases: division or modulus with 0.
+     let x = 1
+     let x /= 0
+     if has('num64')
+         call assert_equal(0x7FFFFFFFFFFFFFFF, x)
+     else
+         call assert_equal(0x7fffffff, x)
+     endif
+ 
+     let x = -1
+     let x /= 0
+     if has('num64')
+         call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
+     else
+         call assert_equal(-0x7fffffff, x)
+     endif
+ 
+     let x = 0
+     let x /= 0
+     if has('num64')
+         call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
+     else
+         call assert_equal(-0x7FFFFFFF - 1, x)
+     endif
+ 
+     let x = 1
+     let x %= 0
+     call assert_equal(0, x)
+ 
+     let x = -1
+     let x %= 0
+     call assert_equal(0, x)
+ 
+     let x = 0
+     let x %= 0
+     call assert_equal(0, x)
+ 
      " Test for string
      let x = 'str'
      let x .= 'ing'
*** ../vim-8.1.0989/src/version.c       2019-03-02 10:13:36.800974804 +0100
--- src/version.c       2019-03-02 11:51:59.125366185 +0100
***************
*** 781,782 ****
--- 781,784 ----
  {   /* Add new patch number below this line */
+ /**/
+     990,
  /**/

-- 
Give a man a computer program and you give him a headache,
but teach him to program computers and you give him the power
to create headaches for others for the rest of his life...
        R. B. Forest

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui