delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1998/08/12/04:51:39

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

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019