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';
 

Reply via email to