Bug 18602 - segfault on a huge switch statement.
Summary: segfault on a huge switch statement.
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.0.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: 18462
  Show dependency treegraph
 
Reported: 2004-11-21 23:16 UTC by Kazu Hirata
Modified: 2004-12-07 21:30 UTC (History)
2 users (show)

See Also:
Host:
Target: i686-pc-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed: 2004-11-21 23:20:22


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kazu Hirata 2004-11-21 23:16:18 UTC
Here is basically the same testcase as PR18599 except that
we have more switch cases.  This testcase segfaults.

cc1 is from today's mainline with checking disabled.

#define CL0(a) case a: return a;
#define CL1(a) CL0(a##0) CL0(a##1) CL0(a##2) CL0(a##3) CL0(a##4) CL0(a##5) \
 CL0(a##6) CL0(a##7) CL0(a##8) CL0(a##9)
#define CL2(a) CL1(a##0) CL1(a##1) CL1(a##2) CL1(a##3) CL1(a##4) CL1(a##5) \
 CL1(a##6) CL1(a##7) CL1(a##8) CL1(a##9)
#define CL3(a) CL2(a##0) CL2(a##1) CL2(a##2) CL2(a##3) CL2(a##4) CL2(a##5) \
 CL2(a##6) CL2(a##7) CL2(a##8) CL2(a##9)
#define CL4(a) CL3(a##0) CL3(a##1) CL3(a##2) CL3(a##3) CL3(a##4) CL3(a##5) \
 CL3(a##6) CL3(a##7) CL3(a##8) CL3(a##9)
#define CL5(a) CL4(a##0) CL4(a##1) CL4(a##2) CL4(a##3) CL4(a##4) CL4(a##5) \
 CL4(a##6) CL4(a##7) CL4(a##8) CL4(a##9)
#define CL6(a) CL5(a##0) CL5(a##1) CL5(a##2) CL5(a##3) CL5(a##4) CL5(a##5) \
 CL5(a##6) CL5(a##7) CL5(a##8) CL5(a##9)

void f();

int
a (int b)
{
  switch (b)
   {
     CL6(1)
   }
}
Comment 1 Andrew Pinski 2004-11-21 23:20:21 UTC
Confirmed, the problem is because of stack overflow.
Either splay_tree_delete_helper needs a little help or the C/C++ front-end needs to stop using splay 
trees.

#553 0x0033a4a0 in splay_tree_delete_helper (sp=0x414012d0, node=0x1b669380) at /Users/
pinskia/src/local3/gcc/libiberty/splay-tree.c:65
Comment 2 Giovanni Bajo 2004-11-22 00:47:14 UTC
I am not sure what we are supposed to do with this. Any kind of tree traversal 
and deletion is inherently recursive, and will hit a segfault sooner or later, 
if you push it hard enough. If an user really needs something degenerate like 
this, she should probably increase her stack limit.

I'm really tempted to mark this as WONTFIX, unless you have a constructive 
suggestion on what to do.
Comment 3 Andrew Pinski 2004-11-22 00:50:21 UTC
Use a seperate stack instead of using function stack.
Comment 4 DJ Delorie 2004-11-22 21:36:31 UTC
Subject: Re:  segfault on a huge switch statement.


> Confirmed, the problem is because of stack overflow.  Either
> splay_tree_delete_helper needs a little help or the C/C++ front-end
> needs to stop using splay trees.

How about this?

/* Deallocate NODE (a member of SP), and all its sub-trees.  */

static void 
splay_tree_delete_helper (sp, node)
     splay_tree sp;
     splay_tree_node node;
{
  splay_tree_node pending = 0;
  splay_tree_node active = 0;

  if (!node)
    return;

#define KDEL(x)  if (sp->delete_key) (*sp->delete_key)(x);
#define VDEL(x)  if (sp->delete_value) (*sp->delete_value)(x);

  KDEL (node->key);
  VDEL (node->value);

  /* We use the "key" field to hold the "next" pointer.  */
  node->key = (splay_tree_key)pending;
  pending = (splay_tree_node)node;

  /* Now, keep processing the pending list until there aren't any
     more.  This is a little more complicated than just recursing, but
     it doesn't toast the stack for large trees.  */

  while (pending)
    {
      active = pending;
      pending = 0;
      while (active)
	{
	  splay_tree_node temp;

	  /* active points to a node which has its key and value
	     deallocated, we just need to process left and right.  */

	  if (active->left)
	    {
	      KDEL (active->left->key);
	      VDEL (active->left->value);
	      active->left->key = (splay_tree_key)pending;
	      pending = (splay_tree_node)(active->left);
	    }
	  if (active->right)
	    {
	      KDEL (active->right->key);
	      VDEL (active->right->value);
	      active->right->key = (splay_tree_key)pending;
	      pending = (splay_tree_node)(active->right);
	    }

	  temp = active;
	  active = (splay_tree_node)(temp->key);
	  (*sp->deallocate) ((char*) temp, sp->allocate_data);
	}
    }
#undef KDEL
#undef VDEL
}
Comment 5 Steven Bosscher 2004-12-07 15:52:32 UTC
DJ, are you going to push your new splay_tree_delete_helper?  If it works,
this fixes a regression wrt. earlier GCCs...
Comment 6 DJ Delorie 2004-12-07 20:02:08 UTC
Subject: Re:  segfault on a huge switch statement.


I have pushed that change out.
Comment 7 Andrew Pinski 2004-12-07 21:30:14 UTC
I have just verified it was fixed, thanks DJ.