hush: rename hush-redir/redir3.tests (ash has redir3.tests which id different)
[oweals/busybox.git] / shell / math.c
index 760645d0f91585bd4781f16d95004ec72c97877b..006221b6a4e7988dbbd82ca5386b55c16afdf834 100644 (file)
@@ -410,15 +410,34 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
                                return "exponent less than 0";
                        c = 1;
                        while (--right_side_val >= 0)
-                           c *= rez;
+                               c *= rez;
                        rez = c;
                }
                else if (right_side_val == 0)
                        return "divide by zero";
-               else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
-                       rez /= right_side_val;
-               else if (op == TOK_REM || op == TOK_REM_ASSIGN)
-                       rez %= right_side_val;
+               else if (op == TOK_DIV || op == TOK_DIV_ASSIGN
+                     || op == TOK_REM || op == TOK_REM_ASSIGN) {
+                       /*
+                        * bash 4.2.45 x86 64bit: SEGV on 'echo $((2**63 / -1))'
+                        *
+                        * MAX_NEGATIVE_INT / -1 = MAX_POSITIVE_INT+1
+                        * and thus is not representable.
+                        * Some CPUs segfault trying such op.
+                        * Others overflow MAX_POSITIVE_INT+1 to
+                        * MAX_NEGATIVE_INT (0x7fff+1 = 0x8000).
+                        * Make sure to at least not SEGV here:
+                        */
+                       if (right_side_val == -1
+                        && rez << 1 == 0 /* MAX_NEGATIVE_INT or 0 */
+                       ) {
+                               right_side_val = 1;
+                       }
+                       if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
+                               rez /= right_side_val;
+                       else {
+                               rez %= right_side_val;
+                       }
+               }
        }
 
        if (is_assign_op(op)) {
@@ -494,18 +513,6 @@ static const char op_tokens[] ALIGN1 = {
 };
 #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7])
 
-const char* FAST_FUNC
-endofname(const char *name)
-{
-       if (!is_name(*name))
-               return name;
-       while (*++name) {
-               if (!is_in_name(*name))
-                       break;
-       }
-       return name;
-}
-
 static arith_t FAST_FUNC
 evaluate_string(arith_state_t *math_state, const char *expr)
 {