samedi 25 juillet 2020

How can I test that a program handles partial read()s and write()s correctly?

It's well-known that the read and write syscalls can operate on fewer bytes than requested. But this is relatively rare and often not tested well. Consider this buggy C program:

#include <unistd.h>

int main(void) {
    const char *buf = "Hello, World!\n";
    size_t count = 14;
    do {
        ssize_t written = write(STDOUT_FILENO, buf, count);
        if(written < 0) return 1;
        /* whoops, forgot to do `buf += written;`! */
        count -= written;
    } while(count);
    return 0;
}

Since it forgets to adjust buf, if the first write were to only write 7 characters, it would end up printing Hello, Hello, instead of Hello, World!. It's really unlikely that you'll ever catch this bug in normal testing, though, since it will virtually always write all 14 characters in one call. Is there some way that I can pessimize reads and writes to do partial writes any time they're allowed while testing, so that these kinds of bugs can be more easily found? A few nice-to-haves:

  • Working on existing binaries rather than needing to recompile
  • Working on statically-linked/non-libc (e.g., Go) binaries
  • Working on more operating systems than just Linux
  • Not breaking programs that use /proc/self/uid_map, inotify, eventfd, or other special FDs that need to (and are guaranteed to be able to) read or write multiple bytes in one syscall

Aucun commentaire:

Enregistrer un commentaire