Sender: juan AT delorie DOT com Message-ID: <387C5F18.D1153AB1@altmayer.com> Disposition-Notification-To: Juan Altmayer Pizzorno Date: Wed, 12 Jan 2000 12:01:44 +0100 From: Juan Altmayer Pizzorno X-Mailer: Mozilla 4.7 [en] (X11; I; Linux 2.2.14 i686) X-Accept-Language: en MIME-Version: 1.0 To: gcc-bugs AT gcc DOT gnu DOT org, pgcc AT delorie DOT com CC: juan AT altmayer DOT com, "=?iso-8859-1?Q?J=FCrgen?= Christoffel" Subject: Possible tail-recursion bug Content-Type: multipart/mixed; boundary="------------9FD3E008FA6FC8546A631DD6" Reply-To: pgcc AT delorie DOT com This is a multi-part message in MIME format. --------------9FD3E008FA6FC8546A631DD6 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hi, I recently reported a bug to the Pentium GCC group where a pointer calculation was changing the value of another variable within a program that originally decoded DNS packets. In the meantime I've confirmed that the bug also happens on other platforms (tested: Pentium II, Pentium Pro, Pentium, SPARC/Solaris) and with various version of the compiler (2.91.66, 2.95.2, pgcc-2.95.2), so I'm following up on this both to pgcc as well as to gcc-bugs. I am attaching the original code below, but apparently the problem is that the parameter 'p' and the variable 'jump' are being allocated in the same location. For example, //--- #include static int ExtractName (char*& p, int n) { char* jump; printf ("p @%X, jump @%X\n", &p, &jump); if (n > 0) return ExtractName (jump, n - 1); return 0; } int main () { char* p; ExtractName (p, 10); return 0; } //--- compiled with "g++ -O -o t2 t2.cxx" produces p @BFFFFB64, jump @BFFFFB34 p @BFFFFB34, jump @BFFFFB34 <-- both allocated in the same location! p @BFFFFB34, jump @BFFFFB34 p @BFFFFB34, jump @BFFFFB34 ... where as if compiled with "g++ -o t2 t2.cxx" it produces p @BFFFFB64, jump @BFFFFB34 p @BFFFFB34, jump @BFFFFB04 p @BFFFFB04, jump @BFFFFAD4 ... Interestingly enough, if I replace if (n > 0) return ExtractName (jump, n - 1); by if (n > 0) { int result = ExtractName (jump, n - 1); return result; } the problem does not occur (perhaps the tail recursion is not recognized?). While an argument could be made that in the example above neither 'jump' nor 'p' are really being used, this is not the case in the (more complicated) original code. Please let me know if there is any way I can help. Thanks .. Juan --------------9FD3E008FA6FC8546A631DD6 Content-Type: text/plain; charset=us-ascii; name="t.cxx" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="t.cxx" // $Id: t.cxx,v 1.14 2000/01/12 09:41:23 juan Exp $ #include typedef unsigned char uchar; /* $ g++ --version pgcc-2.95.2 $ g++ -O6 -o t t.cxx p @BFFFFA58, jump @BFFFFA54 BFFFFAAB == BFFFFAAB ? p @BFFFFA54, jump @BFFFFA54 <--- allocated in same address BFFFFA94 == BFFFFA68 ? <--- changing 'jump' changes 'p' p @BFFFFA54, jump @BFFFFA54 BFFFFA6A == C0002FCA ? p @BFFFFA54, jump @BFFFFA54 */ static int ExtractName (uchar* header, uchar*& p, uchar* end) { uchar* jump; unsigned length; printf ("p @%X, jump @%X\n", (unsigned)&p, (unsigned)&jump); if (p >= end) return 1; while ((length = *p++)) { if (length & 0xc0) { // compute offset in 'length', new 'p' in 'jump' length = ((length & 0x3F) << 8) | *p; printf ("%X == ", (unsigned)p); jump = header + length; printf ("%X ?\n", (unsigned)p); // advance 'p' to final position ++p; return ExtractName (header, jump, end); } else { if (p + length > end) return 1; p += length; } } if (p > end) return 1; return 0; } int main (int argc, char* argv[]) { uchar buffer[] = { 0x00,0x01,0x81,0x80,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x06,0x08,0x75,0x6E,0x69, 0x2D,0x62,0x6F,0x6E,0x6E,0x02,0x64,0x65,0x00,0x00,0x0F,0x00,0x01,0xC0,0x0C,0x00, 0x0F,0x00,0x01,0x00,0x00,0x03,0x84,0x00,0x10,0x00,0x0A,0x06,0x6E,0x6F,0x64,0x65, 0x30,0x33,0x04,0x72,0x68,0x72,0x7A,0xC0,0x0C,0xC0,0x0C,0x00,0x0F,0x00,0x01,0x00, 0x00,0x03,0x84,0x00,0x0B,0x00,0x14,0x06,0x6E,0x6F,0x64,0x65,0x30,0x35,0xC0,0x32, 0xC0,0x0C,0x00,0x02,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x06,0x03,0x4E,0x49,0x43, 0xC0,0x32,0xC0,0x0C,0x00,0x02,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x0D,0x0A,0x6E, 0x6F,0x64,0x65,0x30,0x33,0x2D,0x65,0x6E,0x32,0xC0,0x32,0xC0,0x0C,0x00,0x02,0x00, 0x01,0x00,0x01,0x51,0x80,0x00,0x09,0x06,0x6E,0x6F,0x64,0x65,0x30,0x38,0xC0,0x32, 0xC0,0x0C,0x00,0x02,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x17,0x07,0x77,0x73,0x2D, 0x6D,0x75,0x65,0x31,0x06,0x77,0x69,0x6E,0x2D,0x69,0x70,0x03,0x64,0x66,0x6E,0x02, 0x64,0x65,0x00,0xC0,0x2B,0x00,0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x83, 0xDC,0x12,0x85,0xC0,0x47,0x00,0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x83, 0xDC,0x12,0x87,0xC0,0x5C,0x00,0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x83, 0xDC,0x10,0xDC,0xC0,0x6E,0x00,0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x83, 0xDC,0x0E,0xCB,0xC0,0x87,0x00,0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x83, 0xDC,0x12,0x8A,0xC0,0x9C,0x00,0x01,0x00,0x01,0x00,0x00,0xF2,0x41,0x00,0x04,0xC1, 0xAE,0x4B,0xA6 }; int rc; uchar* end = buffer + sizeof (buffer); uchar* p = buffer + 0x47; if ((rc = ExtractName (buffer, p, end))) exit (1); return 0; } --------------9FD3E008FA6FC8546A631DD6--