Err, the race in io_output() doesn't double-free

The previous commit's message claims the race can lead to duplicated
output, use after free, then double-free.  That's correct only up to
the use after free.  There is no double-free.

Heap corruption (double-free?) has been observed in Changeling,
though.  Player logged in (still in sanctuary), map #, crashed within
removecc()'s free(io->data).  Partial backtrace:

    raise () from /lib64/libc.so.6
    abort () from /lib64/libc.so.6
    __libc_message () from /lib64/libc.so.6
    malloc_printerr () from /lib64/libc.so.6
    removecc (ioq=0x251fd10, cc=468) at ../src/lib/gen/ioqueue.c:350
    ioq_dequeue (ioq=0x251fd10, cc=468) at ../src/lib/gen/ioqueue.c:135
    io_output (iop=0x251fc90, wait=1) at ../src/lib/empthread/io.c:231
    recvclient (cmd=0x258d8e0 "", size=1024) at ../src/lib/player/recvclient.c:82
    getcommand (combufp=0x2557068 "map #1") at ../src/lib/player/empdis.c:84

I haven't been able to reproduce.

To hopefully catch ioqueue going south earlier, make ioq_dequeue()
oops when it can't dequeue as many bytes as requested.
This commit is contained in:
Markus Armbruster 2010-08-29 11:31:02 +02:00
parent d28fbbb186
commit 2bb8923c6f

View file

@ -132,7 +132,9 @@ ioq_peek(struct ioqueue *ioq, char *buf, int cc)
int int
ioq_dequeue(struct ioqueue *ioq, int cc) ioq_dequeue(struct ioqueue *ioq, int cc)
{ {
return removecc(ioq, cc); int res = removecc(ioq, cc);
CANT_HAPPEN(res != cc);
return res;
} }
void void