fix for expmed out-of-bounds array accesses
Joern Rennecke
amylaar@cambridge.redhat.com
Sat Jan 20 15:54:00 GMT 2001
The use of negative costs (from uninitialized memory) for
wider-than-wordsize shifts can lead to incorrect code generation.
Sat Jan 20 23:46:45 2001 J"orn Rennecke <amylaar@redhat.com>
* expmed.c (synth_mult, expand_mult_highpart, expand_divmod): Guard
uses of shift_cost, shiftadd_cost and shiftsub_cost with bound checks.
Index: expmed.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/expmed.c,v
retrieving revision 1.153
diff -p -r1.153 expmed.c
*** expmed.c 2000/12/24 21:20:04 1.153
--- expmed.c 2001/01/20 23:46:07
*************** synth_mult (alg_out, t, cost_limit)
*** 2140,2157 ****
if ((t & 1) == 0)
{
m = floor_log2 (t & -t); /* m = number of low zero bits */
! q = t >> m;
! cost = shift_cost[m];
! synth_mult (alg_in, q, cost_limit - cost);
!
! cost += alg_in->cost;
! if (cost < cost_limit)
{
! struct algorithm *x;
! x = alg_in, alg_in = best_alg, best_alg = x;
! best_alg->log[best_alg->ops] = m;
! best_alg->op[best_alg->ops] = alg_shift;
! cost_limit = cost;
}
}
--- 2140,2160 ----
if ((t & 1) == 0)
{
m = floor_log2 (t & -t); /* m = number of low zero bits */
! if (m < BITS_PER_WORD)
{
! q = t >> m;
! cost = shift_cost[m];
! synth_mult (alg_in, q, cost_limit - cost);
!
! cost += alg_in->cost;
! if (cost < cost_limit)
! {
! struct algorithm *x;
! x = alg_in, alg_in = best_alg, best_alg = x;
! best_alg->log[best_alg->ops] = m;
! best_alg->op[best_alg->ops] = alg_shift;
! cost_limit = cost;
! }
}
}
*************** synth_mult (alg_out, t, cost_limit)
*** 2222,2228 ****
unsigned HOST_WIDE_INT d;
d = ((unsigned HOST_WIDE_INT) 1 << m) + 1;
! if (t % d == 0 && t > d)
{
cost = MIN (shiftadd_cost[m], add_cost + shift_cost[m]);
synth_mult (alg_in, t / d, cost_limit - cost);
--- 2225,2231 ----
unsigned HOST_WIDE_INT d;
d = ((unsigned HOST_WIDE_INT) 1 << m) + 1;
! if (t % d == 0 && t > d && m < BITS_PER_WORD)
{
cost = MIN (shiftadd_cost[m], add_cost + shift_cost[m]);
synth_mult (alg_in, t / d, cost_limit - cost);
*************** synth_mult (alg_out, t, cost_limit)
*** 2241,2247 ****
}
d = ((unsigned HOST_WIDE_INT) 1 << m) - 1;
! if (t % d == 0 && t > d)
{
cost = MIN (shiftsub_cost[m], add_cost + shift_cost[m]);
synth_mult (alg_in, t / d, cost_limit - cost);
--- 2244,2250 ----
}
d = ((unsigned HOST_WIDE_INT) 1 << m) - 1;
! if (t % d == 0 && t > d && m < BITS_PER_WORD)
{
cost = MIN (shiftsub_cost[m], add_cost + shift_cost[m]);
synth_mult (alg_in, t / d, cost_limit - cost);
*************** synth_mult (alg_out, t, cost_limit)
*** 2266,2272 ****
q = t - 1;
q = q & -q;
m = exact_log2 (q);
! if (m >= 0)
{
cost = shiftadd_cost[m];
synth_mult (alg_in, (t - 1) >> m, cost_limit - cost);
--- 2269,2275 ----
q = t - 1;
q = q & -q;
m = exact_log2 (q);
! if (m >= 0 && m < BITS_PER_WORD)
{
cost = shiftadd_cost[m];
synth_mult (alg_in, (t - 1) >> m, cost_limit - cost);
*************** synth_mult (alg_out, t, cost_limit)
*** 2285,2291 ****
q = t + 1;
q = q & -q;
m = exact_log2 (q);
! if (m >= 0)
{
cost = shiftsub_cost[m];
synth_mult (alg_in, (t + 1) >> m, cost_limit - cost);
--- 2288,2294 ----
q = t + 1;
q = q & -q;
m = exact_log2 (q);
! if (m >= 0 && m < BITS_PER_WORD)
{
cost = shiftsub_cost[m];
synth_mult (alg_in, (t + 1) >> m, cost_limit - cost);
*************** expand_mult_highpart (mode, op0, cnst1,
*** 2818,2824 ****
/* Secondly, same as above, but use sign flavor opposite of unsignedp.
Need to adjust the result after the multiplication. */
! if (mul_highpart_cost[(int) mode] + 2 * shift_cost[size-1] + 4 * add_cost < max_cost)
{
mul_highpart_optab = unsignedp ? smul_highpart_optab : umul_highpart_optab;
target = expand_binop (mode, mul_highpart_optab,
--- 2821,2829 ----
/* Secondly, same as above, but use sign flavor opposite of unsignedp.
Need to adjust the result after the multiplication. */
! if (size - 1 < BITS_PER_WORD
! && (mul_highpart_cost[(int) mode] + 2 * shift_cost[size-1] + 4 * add_cost
! < max_cost))
{
mul_highpart_optab = unsignedp ? smul_highpart_optab : umul_highpart_optab;
target = expand_binop (mode, mul_highpart_optab,
*************** expand_mult_highpart (mode, op0, cnst1,
*** 2841,2846 ****
--- 2846,2852 ----
/* Try widening the mode and perform a non-widening multiplication. */
moptab = smul_optab;
if (smul_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
+ && size - 1 < BITS_PER_WORD
&& mul_cost[(int) wider_mode] + shift_cost[size-1] < max_cost)
{
op1 = wide_op1;
*************** expand_mult_highpart (mode, op0, cnst1,
*** 2850,2855 ****
--- 2856,2862 ----
/* Try widening multiplication of opposite signedness, and adjust. */
moptab = unsignedp ? smul_widen_optab : umul_widen_optab;
if (moptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
+ && size - 1 < BITS_PER_WORD
&& (mul_widen_cost[(int) wider_mode]
+ 2 * shift_cost[size-1] + 4 * add_cost < max_cost))
{
*************** expand_divmod (rem_flag, code, mode, op0
*** 3186,3191 ****
--- 3193,3201 ----
{
rtx t1, t2, t3, t4;
+ if (post_shift - 1 >= BITS_PER_WORD)
+ goto fail1;
+
extra_cost = (shift_cost[post_shift - 1]
+ shift_cost[1] + 2 * add_cost);
t1 = expand_mult_highpart (compute_mode, op0, ml,
*************** expand_divmod (rem_flag, code, mode, op0
*** 3210,3215 ****
--- 3220,3229 ----
{
rtx t1, t2;
+ if (pre_shift >= BITS_PER_WORD
+ || post_shift >= BITS_PER_WORD)
+ goto fail1;
+
t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
build_int_2 (pre_shift, 0),
NULL_RTX, 1);
*************** expand_divmod (rem_flag, code, mode, op0
*** 3330,3335 ****
--- 3344,3353 ----
{
rtx t1, t2, t3;
+ if (post_shift >= BITS_PER_WORD
+ || size - 1 >= BITS_PER_WORD)
+ goto fail1;
+
extra_cost = (shift_cost[post_shift]
+ shift_cost[size - 1] + add_cost);
t1 = expand_mult_highpart (compute_mode, op0, ml,
*************** expand_divmod (rem_flag, code, mode, op0
*** 3356,3361 ****
--- 3374,3383 ----
{
rtx t1, t2, t3, t4;
+ if (post_shift >= BITS_PER_WORD
+ || size - 1 >= BITS_PER_WORD)
+ goto fail1;
+
ml |= (~(unsigned HOST_WIDE_INT) 0) << (size - 1);
extra_cost = (shift_cost[post_shift]
+ shift_cost[size - 1] + 2 * add_cost);
*************** expand_divmod (rem_flag, code, mode, op0
*** 3439,3461 ****
if (mh)
abort ();
! t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
! build_int_2 (size - 1, 0), NULL_RTX, 0);
! t2 = expand_binop (compute_mode, xor_optab, op0, t1,
! NULL_RTX, 0, OPTAB_WIDEN);
! extra_cost = (shift_cost[post_shift]
! + shift_cost[size - 1] + 2 * add_cost);
! t3 = expand_mult_highpart (compute_mode, t2, ml,
! NULL_RTX, 1,
! max_cost - extra_cost);
! if (t3 != 0)
{
! t4 = expand_shift (RSHIFT_EXPR, compute_mode, t3,
! build_int_2 (post_shift, 0),
! NULL_RTX, 1);
! quotient = expand_binop (compute_mode, xor_optab,
! t4, t1, tquotient, 0,
! OPTAB_WIDEN);
}
}
}
--- 3461,3488 ----
if (mh)
abort ();
! if (post_shift < BITS_PER_WORD
! && size - 1 < BITS_PER_WORD)
{
! t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
! build_int_2 (size - 1, 0),
! NULL_RTX, 0);
! t2 = expand_binop (compute_mode, xor_optab, op0, t1,
! NULL_RTX, 0, OPTAB_WIDEN);
! extra_cost = (shift_cost[post_shift]
! + shift_cost[size - 1] + 2 * add_cost);
! t3 = expand_mult_highpart (compute_mode, t2, ml,
! NULL_RTX, 1,
! max_cost - extra_cost);
! if (t3 != 0)
! {
! t4 = expand_shift (RSHIFT_EXPR, compute_mode, t3,
! build_int_2 (post_shift, 0),
! NULL_RTX, 1);
! quotient = expand_binop (compute_mode, xor_optab,
! t4, t1, tquotient, 0,
! OPTAB_WIDEN);
! }
}
}
}
More information about the Gcc-patches
mailing list