true_regnum(x) returns only positive numbers for a pseudo register, if REG_P(x) 
 
is true.  
  
reload.c, function decompose, line 2363 (CVS HEAD version):  
  
   case REG:  
     val.reg_flag = 1;  
     val.start = true_regnum (x);  
      if (val.start < 0)  
        {  
          /* A pseudo with no hard reg.  */  
          val.start = REGNO (x);  
          val.end = val.start + 1;  
        }  
      else  
        /* A hard reg.  */  
        val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];  
  
  
So if decompose is called with an pseudo register, which is not renumbered,  
val.end = val.start + hard_regno_nregs[val.start][GET_MODE (x)];  
is executed. val.start contains in that case a number >= FIRST_PSEUDO_REGISTER, 
 
which is so an access over the array-bounds of hard_regno_nregs.  
  
I suggest to put a   
gcc_assert (val.start <FIRST_PSEUDO_REGISTER);  
 before the instruction, so that such an error will be found.  
  
GCC calls decompose with a not renumbered register, if the following conditions 
 
are fullfiled:  
*All for allocation available registeres are in use  
*An operation has for an operand an constraint like "=&rm" and the value is an  
pseudo register.  
  
For i686 and gcc version 4.0.0 20041207 (experimental), such an assert fails   
for the following example (compiled with -O1,-O2,-O3 or -Os):  
long a,b,c,d,e,f,g,h,i;  
int test()  
{  
  long x1,x2,x3,l,l1,l2;  
  t1(&x1,&x2,&x3);  
  x1+=2;  
  l=c+2;  
  l1=d+2;  
  l2=e+2;  
  asm("nop # %0 %1 %2 %3 %4 %5 %6 %7 %8 %9": "=a"(a), "=b"(b), "=c"(c),  
 "=d"(d), "=&mr"(e), "=&mr"(f),"=&rm"(x2),"=&rm"(l2): "2"(x1),"0"(x2),  
"1"(e),"3"(f),"rm"(l),"rm"(l1),"rm"(l2),"m"(x3),"g"(x2));  
  t1(x1,x2,x3+l2);  
}  
  
In that case, hard_regno_nregs[58][SImode] will be accessed. If some code is  
inserted before the assignement of l2, l2 will get an higher number, which will 
 
cause an segmentation fault.  
  
As an fix, maybe changing the if-statement to  
if (val.start < 0||val.start>=FIRST_PSEUDO_REGISTER)  
can help, as the comment says, that the then-part of the if statement should be 
 
used for pseudo registers. If that is correct, I can't tell.  
  
For the SUBREG-case in decompose, there is a similar issue.  
  
mfg Martin Kögler  
[EMAIL PROTECTED]

-- 
           Summary: decompose (reload.c) can be forced to access
                    hard_regno_nregs over its array bounds
           Product: gcc
           Version: 4.0.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: other
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: e9925248 at stud4 dot tuwien dot ac dot at
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: i686-pc-linux-gnu (not i686 spezific)
  GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18877

Reply via email to