Subject: bin/5071: "lpq user" causes segmentation fault
To: None <gnats-bugs@gnats.netbsd.org>
From: None <Havard.Eidnes@runit.sintef.no>
List: netbsd-bugs
Date: 02/26/1998 14:04:10
>Number:         5071
>Category:       bin
>Synopsis:       "lpq user" causes segmentation fault
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Feb 26 11:05:01 1998
>Last-Modified:
>Originator:     Havard Eidnes
>Organization:
	RUNIT A/S
>Release:        1.3_ALPHA, user-land Dec 3 1997 vintage
>Environment:
System: NetBSD vader.runit.sintef.no 1.3_ALPHA NetBSD 1.3_ALPHA (VADER) #11: Sat Nov 8 20:20:41 MET 1997 he@vader.runit.sintef.no:/usr/src/sys/arch/i386/compile/VADER i386


>Description:
	Doing "lpq user" causes a segmentation fault.
>How-To-Repeat:
	See above.
>Fix:
	No fix supplied here, although I can point at the piece of the
	code where this bug is to be found.  Specifically,
	/usr/src.usr.sbin/lpr/common_source/displayq.c contains this sequence
	of code:

        (void)snprintf(line, sizeof(line), "%c%s", format + '\3', RP);
        cp = line;
        for (i = 0; i < requests && cp-line+10 < sizeof(line) - 1; i++) {
                cp += strlen(cp);
                (void)snprintf(cp, line - cp, " %d", requ[i]);
        }
        for (i = 0; i < users && cp - line + 1 + strlen(user[i]) <
            sizeof(line) - 1; i++) {
                cp += strlen(cp);
                if (cp - line > sizeof(line) - 1)
                        break;
                *cp++ = ' ';
                (void)strncpy(cp, user[i], line - cp - 1);
        }

	The problem here is that 'cp' ends up as larger than 'line', and
	this causes "line - cp - 1" to take a small negative value.  This
	in turn is implicitly cast via the "size_t" argument type of strncpy,
	which on i386 is "unsigned int", and it is downhill from there (it
	crashes in the last strncpy() call.

	I would have thought that the expression

		min(sizeof(line) - (cp - line) - 1, strlen(user[i])

	should be used as the last argument to the strncpy call.

	With the attached patch at least lpq no longer segfaults in this
	situation.  I'm sure a stylistically prettier solution can be found.

--- displayq.c.dist	Mon Oct  6 13:34:01 1997
+++ displayq.c	Thu Feb 26 14:01:33 1998
@@ -244,5 +244,8 @@
 			break;
 		*cp++ = ' ';
-		(void)strncpy(cp, user[i], line - cp - 1);
+#define min(a,b) ((a)<(b) ? (a) : (b))
+		(void)strncpy(cp, user[i], 
+			min(sizeof(line) - (cp-line) - 1, strlen(user[i])));
+#undef min
 	}
 	(void)strncat(line, "\n", sizeof(line) - strlen(line) - 1);
>Audit-Trail:
>Unformatted: