Subject: bin/3285: dmesg sometimes fall into infinite loop
To: None <gnats-bugs@gnats.netbsd.org>
From: None <enami@ba2.so-net.or.jp>
List: netbsd-bugs
Date: 03/03/1997 22:15:41
>Number:         3285
>Category:       bin
>Synopsis:       dmesg sometimes fall into infinite loop
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Mar  3 06:20:07 1997
>Last-Modified:
>Originator:     enami tsugutomo
>Organization:
	An individual
>Release:        NetBSD-current 1997 Mar 01
>Environment:
System: NetBSD pavlov.enami.ba2.so-net.or.jp 1.2C NetBSD 1.2C (PAVLOV) #164: Sat Feb 8 01:00:12 JST 1997 enami@pavlov.enami.ba2.so-net.or.jp:/b/netbsd/kernel/compile/PAVLOV i386


>Description:
	The command dmesg sometimes fall into infinit loop.  I
	observed it when (pointer to msgbuf)->msg_bufx is one.
	Probably it occurs when it is zero.

	Here is a piece of code quoted from dmesg.c:

	p = cur.msg_bufc + cur.msg_bufx;
	ep = cur.msg_bufc + cur.msg_bufx - 1;
	for (newl = skip = 0; p != ep; ++p) {
		if (p == cur.msg_bufc + MSG_BSIZE)
			p = cur.msg_bufc;
		ch = *p;

	In above code, when testing `p != ep', variable `p' will have
	a value of range between cur.msg_bufc + 1 and cur.msg_bufc +
	MSG_BSIZE (except the frist test which always fails).  But
	variable `ep' will have a value of range between cur.msg_bufc
	- 1 and cur.msg_bufc + MSG_BSIZE - 1.

	Then, it is obvious that if cur.msg_bufx is zero or one, the
	loop never exits.

>How-To-Repeat:
	Call dmesg when (pointer to msgbuf)->msg_bufx is one.
>Fix:
	Here is a patch I'm currenty using.

Index: dmesg.c
===================================================================
RCS file: /a/cvsroot/NetBSD/src/sbin/dmesg/dmesg.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 dmesg.c
--- dmesg.c	1996/11/16 10:06:41	1.1.1.1
+++ dmesg.c	1997/02/22 15:18:09
@@ -126,10 +126,10 @@
 	 * The message buffer is circular; start at the read pointer, and
 	 * go to the write pointer - 1.
 	 */
-	p = cur.msg_bufc + cur.msg_bufx;
-	ep = cur.msg_bufc + cur.msg_bufx - 1;
-	for (newl = skip = 0; p != ep; ++p) {
-		if (p == cur.msg_bufc + MSG_BSIZE)
+	p = ep = cur.msg_bufc + (cur.msg_bufx - 1 + MSG_BSIZE) % MSG_BSIZE;
+	newl = skip = 0;
+	do {
+		if (++p == cur.msg_bufc + MSG_BSIZE)
 			p = cur.msg_bufc;
 		ch = *p;
 		/* Skip "\n<.*>" syslog sequences. */
@@ -150,7 +150,7 @@
 			(void)putchar(buf[0]);
 		else
 			(void)printf("%s", buf);
-	}
+	} while (p != ep);
 	if (!newl)
 		(void)putchar('\n');
 	exit(0);
>Audit-Trail:
>Unformatted: