--- gdb-6.6.90-orig/gdb/stabsread.c Thu Sep 20 11:58:55 2007 +++ gdb-6.6.90/gdb/stabsread.c Fri Sep 21 09:41:32 2007 @@ -3704,6 +3704,7 @@ read_huge_number (char **pp, int end, in char *p = *pp; int sign = 1; int sign_bit; + int sign_bit_set = 0; long n = 0; long sn = 0; int radix = 10; @@ -3728,38 +3729,79 @@ read_huge_number (char **pp, int end, in } twos_complement_representation = radix == 8 && twos_complement_bits > 0; + if (twos_complement_representation) + { + int len, indpos, i, sign_byte, sign_bit_pos; + char *endpos; + len = strlen(p); + endpos = strchr(p,end); + if ((endpos != NULL) && (len > endpos - p)) + len = endpos -p -1; + indpos = 0; + sign_byte = twos_complement_bits / 3; + sign_bit_pos = (twos_complement_bits % 3 + 2) % 3; + for (i=len; i>=0; i--) + { + c = p[i]; + if (c >= '0' && c < ('0' + radix)) + { + /* This is a valid numeral. */ + if (indpos == sign_byte) + { + int val, uval; + val = c - '0'; + if (val & (1 << sign_bit_pos)) + { + /* This numeral is signed. */ + sign *= -1; + sign_bit_set = 1; + /* Clear sign bit. */ + uval = (val - (1 << sign_bit_pos)); + /* No bit higher than the sign bit should be set. */ + if (uval > (1 << sign_bit_pos)) + { + nbits = -1; + if (bits != NULL) + *bits = nbits; + return 0; + } + c = '0' + uval; + p[i] = c; + + } + } + else if (indpos > sign_byte) + { + /* allow only zeroes above sign_byte. */ + if (c != '0') + { + nbits = -1; + if (bits != NULL) + *bits = nbits; + return 0; + }; + } + indpos++; + } + else + { + nbits = -1; + if (bits != NULL) + *bits = nbits; + return 0; + } + } + + } upper_limit = LONG_MAX / radix; while ((c = *p++) >= '0' && c < ('0' + radix)) { if (n <= upper_limit) { - if (twos_complement_representation) - { - /* Octal, signed, twos complement representation. In this case, - sn is the signed value, n is the corresponding absolute - value. signed_bit is the position of the sign bit in the - first three bits. */ - if (sn == 0) - { - sign_bit = (twos_complement_bits % 3 + 2) % 3; - sn = c - '0' - ((2 * (c - '0')) | (2 << sign_bit)); - } - else - { - sn *= radix; - sn += c - '0'; - } - - if (sn < 0) - n = -sn; - } - else - { - /* unsigned representation */ - n *= radix; - n += c - '0'; /* FIXME this overflows anyway */ - } + /* unsigned representation */ + n *= radix; + n += c - '0'; /* FIXME this overflows anyway */ } else overflow = 1; @@ -3799,7 +3841,7 @@ read_huge_number (char **pp, int end, in *pp = p; if (overflow) { - if (nbits == 0) + if ((nbits == 0) && (radix != 8)) { /* Large decimal constants are an error (because it is hard to count how many bits are in them). */ @@ -3812,6 +3854,8 @@ read_huge_number (char **pp, int end, in the number of bits. */ if (sign == -1) ++nbits; + if (sign_bit_set) + nbits = twos_complement_bits; if (bits) *bits = nbits; } @@ -3819,10 +3863,7 @@ read_huge_number (char **pp, int end, in { if (bits) *bits = 0; - if (twos_complement_representation) - return sn; - else - return n * sign; + return n * sign; } /* It's *BITS which has the interesting information. */ return 0;