Module Name:    src
Committed By:   rillig
Date:           Fri Oct 29 19:12:49 UTC 2021

Modified Files:
        src/usr.bin/indent: indent.c io.c pr_comment.c

Log Message:
indent: fix undefined behavior in buffer handling

Adding an arbitrary integer to a pointer may result in an out of bounds
pointer, so replace the addition with a pointer subtraction.

In the buffer handling functions, handle 'buf' and 'l' before 's' and
'e', since they are pairs.

In inbuf_read_line, use 's' instead of 'buf' to make the code easier to
understand for human readers.

No functional change.


To generate a diff of this commit:
cvs rdiff -u -r1.172 -r1.173 src/usr.bin/indent/indent.c
cvs rdiff -u -r1.105 -r1.106 src/usr.bin/indent/io.c
cvs rdiff -u -r1.88 -r1.89 src/usr.bin/indent/pr_comment.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/indent/indent.c
diff -u src/usr.bin/indent/indent.c:1.172 src/usr.bin/indent/indent.c:1.173
--- src/usr.bin/indent/indent.c:1.172	Fri Oct 29 18:50:52 2021
+++ src/usr.bin/indent/indent.c	Fri Oct 29 19:12:48 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: indent.c,v 1.172 2021/10/29 18:50:52 rillig Exp $	*/
+/*	$NetBSD: indent.c,v 1.173 2021/10/29 19:12:48 rillig Exp $	*/
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
@@ -43,7 +43,7 @@ static char sccsid[] = "@(#)indent.c	5.1
 
 #include <sys/cdefs.h>
 #if defined(__NetBSD__)
-__RCSID("$NetBSD: indent.c,v 1.172 2021/10/29 18:50:52 rillig Exp $");
+__RCSID("$NetBSD: indent.c,v 1.173 2021/10/29 19:12:48 rillig Exp $");
 #elif defined(__FreeBSD__)
 __FBSDID("$FreeBSD: head/usr.bin/indent/indent.c 340138 2018-11-04 19:24:49Z oshogbo $");
 #endif
@@ -390,11 +390,11 @@ buf_init(struct buffer *buf)
 {
     size_t size = 200;
     buf->buf = xmalloc(size);
-    buf->buf[0] = ' ';		/* allow accessing buf->e[-1] */
-    buf->buf[1] = '\0';
-    buf->s = buf->buf + 1;
+    buf->l = buf->buf + size - 5 /* safety margin */;
+    buf->s = buf->buf + 1;	/* allow accessing buf->e[-1] */
     buf->e = buf->s;
-    buf->l = buf->buf + size - 5;	/* safety margin */
+    buf->buf[0] = ' ';
+    buf->buf[1] = '\0';
 }
 
 static size_t
@@ -404,20 +404,21 @@ buf_len(const struct buffer *buf)
 }
 
 void
-buf_expand(struct buffer *buf, size_t desired_size)
+buf_expand(struct buffer *buf, size_t add_size)
 {
-    size_t nsize = (size_t)(buf->l - buf->s) + 400 + desired_size;
+    size_t new_size = (size_t)(buf->l - buf->s) + 400 + add_size;
     size_t len = buf_len(buf);
-    buf->buf = xrealloc(buf->buf, nsize);
-    buf->e = buf->buf + len + 1;
-    buf->l = buf->buf + nsize - 5;
+    buf->buf = xrealloc(buf->buf, new_size);
+    buf->l = buf->buf + new_size - 5;
     buf->s = buf->buf + 1;
+    buf->e = buf->s + len;
+    /* At this point, the buffer may not be null-terminated anymore. */
 }
 
 static void
 buf_reserve(struct buffer *buf, size_t n)
 {
-    if (buf->e + n >= buf->l)
+    if (n >= (size_t)(buf->l - buf->e))
 	buf_expand(buf, n);
 }
 
@@ -467,7 +468,9 @@ main_init_globals(void)
 
     inp.buf = xmalloc(10);
     inp.l = inp.buf + 8;
-    inp.s = inp.e = inp.buf;
+    inp.s = inp.buf;
+    inp.e = inp.buf;
+
     line_no = 1;
     had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
 

Index: src/usr.bin/indent/io.c
diff -u src/usr.bin/indent/io.c:1.105 src/usr.bin/indent/io.c:1.106
--- src/usr.bin/indent/io.c:1.105	Fri Oct 29 18:18:03 2021
+++ src/usr.bin/indent/io.c	Fri Oct 29 19:12:48 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: io.c,v 1.105 2021/10/29 18:18:03 rillig Exp $	*/
+/*	$NetBSD: io.c,v 1.106 2021/10/29 19:12:48 rillig Exp $	*/
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
@@ -43,7 +43,7 @@ static char sccsid[] = "@(#)io.c	8.1 (Be
 
 #include <sys/cdefs.h>
 #if defined(__NetBSD__)
-__RCSID("$NetBSD: io.c,v 1.105 2021/10/29 18:18:03 rillig Exp $");
+__RCSID("$NetBSD: io.c,v 1.106 2021/10/29 19:12:48 rillig Exp $");
 #elif defined(__FreeBSD__)
 __FBSDID("$FreeBSD: head/usr.bin/indent/io.c 334927 2018-06-10 16:44:18Z pstef $");
 #endif
@@ -448,8 +448,8 @@ inbuf_read_line(void)
     inp.s = inp.buf;
     inp.e = p;
 
-    if (p - inp.buf >= 3 && p[-3] == '*' && p[-2] == '/') {
-	if (strncmp(inp.buf, "/**INDENT**", 11) == 0)
+    if (p - inp.s >= 3 && p[-3] == '*' && p[-2] == '/') {
+	if (strncmp(inp.s, "/**INDENT**", 11) == 0)
 	    inbuf_read_line();	/* flush indent error message */
 	else
 	    parse_indent_comment();

Index: src/usr.bin/indent/pr_comment.c
diff -u src/usr.bin/indent/pr_comment.c:1.88 src/usr.bin/indent/pr_comment.c:1.89
--- src/usr.bin/indent/pr_comment.c:1.88	Fri Oct 29 17:50:37 2021
+++ src/usr.bin/indent/pr_comment.c	Fri Oct 29 19:12:48 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: pr_comment.c,v 1.88 2021/10/29 17:50:37 rillig Exp $	*/
+/*	$NetBSD: pr_comment.c,v 1.89 2021/10/29 19:12:48 rillig Exp $	*/
 
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
@@ -43,7 +43,7 @@ static char sccsid[] = "@(#)pr_comment.c
 
 #include <sys/cdefs.h>
 #if defined(__NetBSD__)
-__RCSID("$NetBSD: pr_comment.c,v 1.88 2021/10/29 17:50:37 rillig Exp $");
+__RCSID("$NetBSD: pr_comment.c,v 1.89 2021/10/29 19:12:48 rillig Exp $");
 #elif defined(__FreeBSD__)
 __FBSDID("$FreeBSD: head/usr.bin/indent/pr_comment.c 334927 2018-06-10 16:44:18Z pstef $");
 #endif
@@ -58,7 +58,7 @@ __FBSDID("$FreeBSD: head/usr.bin/indent/
 static void
 com_add_char(char ch)
 {
-    if (com.e + 1 >= com.l)
+    if (1 >= com.l - com.e)
 	buf_expand(&com, 1);
     *com.e++ = ch;
 }
@@ -69,7 +69,7 @@ com_add_delim(void)
     if (!opt.star_comment_cont)
 	return;
     size_t len = 3;
-    if (com.e + len >= com.l)
+    if (len >= (size_t)(com.l - com.e))
 	buf_expand(&com, len);
     memcpy(com.e, " * ", len);
     com.e += len;
@@ -78,7 +78,7 @@ com_add_delim(void)
 static void
 com_terminate(void)
 {
-    if (com.e + 1 >= com.l)
+    if (1 >= com.l - com.e)
 	buf_expand(&com, 1);
     *com.e = '\0';
 }
@@ -190,6 +190,9 @@ process_comment(void)
 	/*
 	 * XXX: ordered comparison between pointers from different objects
 	 * invokes undefined behavior (C99 6.5.8).
+	 *
+	 * XXX: It's easier to understand if inp.s is used instead of inp.buf,
+	 * since inp.buf is only intended to be used for allocation purposes.
 	 */
 	start = inp.s >= save_com && inp.s < save_com + sc_size ?
 	    sc_buf : inp.buf;

Reply via email to