Err, the race in io_output() doesn't double-free
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 29 Aug 2010 09:31:02 +0000 (11:31 +0200)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 29 Aug 2010 09:31:02 +0000 (11:31 +0200)
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.

src/lib/gen/ioqueue.c

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