ash,hush: do not segfault on $((2**63 / -1))
No binary (build failed)
—
(log yok)
| @@ -415,10 +415,29 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_ | |
| } | |
| 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 overfolw 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)) { | |