Possible tail-recursion bug

Juan Altmayer Pizzorno juan@altmayer.com
Wed Jan 12 02:59:00 GMT 2000


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 <stdio.h>

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
// $Id: t.cxx,v 1.14 2000/01/12 09:41:23 juan Exp $

#include <stdio.h>
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;
}


More information about the Gcc-bugs mailing list