BR 2010180: outobj: Garbage may be written in a last PUBDEF
commit1b67bd25b20b153c0fdc799c28250b9e259221ce
authorSlavik Gnatenko <moveton@users.sourceforge.net>
Sun, 20 Jul 2008 02:27:41 +0000 (19 19:27 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Sun, 20 Jul 2008 02:27:41 +0000 (19 19:27 -0700)
tree08c276f76eb380386573b6d7e5c92836c9a8cfed
parent4fb7ed0566cdc64fb4339d432b481909d95b22a7
BR 2010180: outobj: Garbage may be written in a last PUBDEF

The testcase illustrates the problem. After "nasm -f obj
alonesym.nasm"
let's look to dump:

======
PUBDEF386(91) recnum:5, offset:0000005bh, len:03f9h, chksum:bbh(bb)
Group: 0, Seg: 1
00020000h - 'sym0000' Type:0
00020004h - 'sym0001' Type:0
....
00020134h - 'sym0077' Type:0

PUBDEF(90) recnum:6, offset:00000457h, len:000ah, chksum:b6h(b6)
Group: 0, Seg: 1
00000138h - 's' Type:2
0000b600h - '' Type:0
======

The problem is while 's' offset is 20138h it is marked as type 90h not
91h.  The root cause is located in obj_x():

static ObjRecord *obj_x(ObjRecord * orp, uint32_t val)
{
    if (orp->type & 1)
     orp->x_size = 32;
    if (val > 0xFFFF)
        orp = obj_force(orp, 32);
    if (orp->x_size == 32)
        return (obj_dword(orp, val));
    orp->x_size = 16;
    return (obj_word(orp, val));
}

It sets up x_size and than writes data. In the testcase data are the
offset and this offset overflows a record. In this case the record is
emitted and its x_size is cleared. Because this is last PUBDEF the new
record with only 's' symbol is emitted also but its x_size is not 32
(it's still zero) so obj_fwrite doesn't switch to 91h type.

The problem seems to be very generic and expected to be occurred on
many other record types as well.

        ----

And the fix is simple:

if (orp->x_size == 32)
{
  ObjRecord * nxt = obj_dword(orp, val);
  nxt->x_size = 32; /* x_size is cleared when a record overflows */
  return nxt;
}
output/outobj.c
test/alonesym-obj.asm [new file with mode: 0644]