ash,hush: do not segfault on $((2**63 / -1))
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
08a5dab181
commit
8a475def9e
23
shell/math.c
23
shell/math.c
@ -415,11 +415,30 @@ 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)
|
||||
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 if (op == TOK_REM || op == TOK_REM_ASSIGN)
|
||||
else {
|
||||
rez %= right_side_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_assign_op(op)) {
|
||||
char buf[sizeof(arith_t)*3 + 2];
|
||||
|
Loading…
Reference in New Issue
Block a user