Mail Archives: djgpp-workers/1998/08/12/04:51:39
I have never really dug deep enough into syms.c, so the following is
based on a very limited study, and only at the source level. So
please check my assertions carefully, do not take them for granted ;-).
On Tue, 11 Aug 1998, Gurunandan R. Bhat wrote:
> Consider what happens when the location l is the last line number info
> structure (index = n-1). This is set correctly, but then l++ makes l point
> outside the space of line number info structures. The loop to convert
> relative line numbers to absolute line numbers goes haywire, and over-writes
> malloc's internal tables.
That's not what I think goes on here. The total number of elements in
the array l[] is the number of lines in the function to which those
lines belong. That is, l[k] holds the information about k'th
``breakpointable'' line of the function. So l++ just advances from
the first line of the function to the next:
> l->l_lnno = lbase;
> l++;
Since l->l_lnno for the first line in the function is always zero, the
first line above effectively adds lbase to l[0].l_lnno; l++ then
advances to to the structure which describes the next "breakpointable"
line.
The way I see it, the problem might be in the termination condition of
the ensuing loop:
> for (i2=0; l[i2].l_lnno; i2++)
> l[i2].l_lnno += lbase;
This assumes that the lines' info for the function being processed is
terminated by an entry whose l_lnno member is zero. However, <coff.h>
says this:
/********************** LINE NUMBERS **********************/
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
This only promises that each entry will *begin* with a zero l_lnno,
but it says nothing about how the last entry *ends*. This might cause
problems when processing the last entry. Checking l[i2] against the
end of f_lnno[] might help.
There's also something else that bothers me. Earlier, you said that
in the case where FSDB crashed, lbase was -1. This seems like a bug,
right there, even before l[i2] is dereferenced: lbase should be a
non-negative number, right?
This leads me to another aspect of the code that I find unsafe. Look
how lbase is computed:
> int lbase = f_aux[i+1].x_sym.x_misc.x_lnsz.x_lnno - 1;
I'm worried about the f_aux[i+1] thing. Here's how f_aux is defined:
f_symtab = (SYMENT *)malloc(f_fh.f_nsyms * SYMESZ);
fread(f_symtab, SYMESZ, f_fh.f_nsyms, fd);
f_aux = (AUXENT *)f_symtab;
In other words, f_aux is an array of f_fh.f_nsyms elements, exactly
like f_symtab is. So f_aux[i+1] looks beyond the end of f_symtab[]
array on the last pass through the loop, since then the index i has
the value f_fh.f_nsyms.
Maybe that's how that negative lbase is born? Could you tell what is
the value of i when the offending loop corrupts the pointer maintained
by `malloc'?
Btw, there are a few more uses of i+1 throughout the code.
- Raw text -