Date: Wed, 12 Aug 1998 11:50:56 +0300 (IDT) From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il> To: "Gurunandan R. Bhat" <grbhat AT unigoa DOT ernet DOT in> cc: djgpp-workers AT delorie DOT com Subject: Re: [grbhat AT unigoa DOT ernet DOT in: Problem with process_coff()] In-Reply-To: <Pine.LNX.3.91.980811110423.4530A-100000@aditya.unigoa.ernet.in> Message-ID: <Pine.SUN.3.91.980812114947.16932M-100000@is> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk 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.