Module Name: src Committed By: rillig Date: Sat Feb 13 09:28:27 UTC 2021
Modified Files: src/tests/lib/libcurses/slave: slave.c Log Message: tests/libcurses: fix reading from the parent process In case of a short read, processing the incomplete data invoked undefined behavior. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/tests/lib/libcurses/slave/slave.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/lib/libcurses/slave/slave.c diff -u src/tests/lib/libcurses/slave/slave.c:1.14 src/tests/lib/libcurses/slave/slave.c:1.15 --- src/tests/lib/libcurses/slave/slave.c:1.14 Sat Feb 13 09:18:12 2021 +++ src/tests/lib/libcurses/slave/slave.c Sat Feb 13 09:28:27 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: slave.c,v 1.14 2021/02/13 09:18:12 rillig Exp $ */ +/* $NetBSD: slave.c,v 1.15 2021/02/13 09:28:27 rillig Exp $ */ /*- * Copyright 2009 Brett Lymn <bl...@netbsd.org> @@ -32,6 +32,7 @@ #include <sys/ioctl.h> #include <unistd.h> #include <err.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -50,6 +51,31 @@ static const char *returns_enum_names[] }; #endif +static bool +try_read_from_director(void *data, size_t n) +{ + ssize_t nread = read(from_director, data, n); + if (nread < 0) + err(2, "error reading from command pipe"); + if (nread == 0) + return false; + if ((size_t)nread != n) + errx(2, "short read from command pipe: expected %zu, got %zu", + n, (size_t)nread); + return true; +} + +static void +read_from_director(void *data, size_t n) +{ + ssize_t nread = read(from_director, data, n); + if (nread < 0) + err(2, "error reading from command pipe"); + if ((size_t)nread != n) + errx(2, "short read from command pipe: expected %zu, got %zu", + n, (size_t)nread); +} + /* * Read the command pipe for the function to execute, gather the args * and then process the command. @@ -59,23 +85,16 @@ process_commands(void) { int len, maxlen, argslen, i, ret, type; char *cmdbuf, *tmpbuf, **args, **tmpargs; - ssize_t nread; len = maxlen = 30; if ((cmdbuf = malloc(maxlen)) == NULL) err(1, "slave cmdbuf malloc failed"); - for (;;) { - if ((nread = read(from_director, &type, sizeof(int))) < 0) - err(1, "slave command type read failed"); - if (nread == 0) - break; - + while (try_read_from_director(&type, sizeof type)) { if (type != data_string) errx(1, "Unexpected type for command, got %d", type); - if (read(from_director, &len, sizeof(int)) < 0) - err(1, "slave command len read failed"); + read_from_director(&len, sizeof len); if ((len + 1) > maxlen) { maxlen = len + 1; @@ -85,18 +104,14 @@ process_commands(void) cmdbuf = tmpbuf; } - if (read(from_director, cmdbuf, len) < 0) - err(1, "slave command read failed"); + read_from_director(cmdbuf, len); cmdbuf[len] = '\0'; argslen = 0; args = NULL; do { - if (read(from_director, &type, sizeof(int)) < 0) - err(1, "slave arg type read failed"); - - if (read(from_director, &len, sizeof(int)) < 0) - err(1, "slave arg len read failed"); + read_from_director(&type, sizeof type); + read_from_director(&len, sizeof len); if (len >= 0) { tmpargs = realloc(args, @@ -120,8 +135,7 @@ process_commands(void) else args[argslen][0] = '\0'; } else { - read(from_director, args[argslen], - len); + read_from_director(args[argslen], len); if (type != data_byte) args[argslen][len] = '\0';