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