Module Name:    src
Committed By:   rillig
Date:           Sat Feb 26 20:36:11 UTC 2022

Modified Files:
        src/tests/usr.bin/xlint/lint1: d_gcc_compound_statements2.c
            t_integration.sh
        src/usr.bin/xlint/lint1: cgram.y externs1.h tree.c

Log Message:
lint: fix memory corruption in statement expressions (since 2021-12-17)

The commit that introduced the assertion failure looks innocent, it only
adds a few predefined functions for GCC mode.  Nevertheless, before that
commit, lint consistently complained about 'error: void type illegal in
expression [109]', which doesn't make sense either.

This fix also removes the creative use of the initialization stack to
store the type of the statement expression.  Having a separate stack for
these statement expressions makes the code easier to understand.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 \
    src/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c
cvs rdiff -u -r1.74 -r1.75 src/tests/usr.bin/xlint/lint1/t_integration.sh
cvs rdiff -u -r1.380 -r1.381 src/usr.bin/xlint/lint1/cgram.y
cvs rdiff -u -r1.145 -r1.146 src/usr.bin/xlint/lint1/externs1.h
cvs rdiff -u -r1.403 -r1.404 src/usr.bin/xlint/lint1/tree.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/usr.bin/xlint/lint1/d_gcc_compound_statements2.c
diff -u src/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c:1.4 src/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c:1.5
--- src/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c:1.4	Fri Sep 10 20:02:51 2021
+++ src/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c	Sat Feb 26 20:36:11 2022
@@ -1,13 +1,18 @@
-/*	$NetBSD: d_gcc_compound_statements2.c,v 1.4 2021/09/10 20:02:51 rillig Exp $	*/
+/*	$NetBSD: d_gcc_compound_statements2.c,v 1.5 2022/02/26 20:36:11 rillig Exp $	*/
 # 3 "d_gcc_compound_statements2.c"
 
-/* GCC compound statements with non-expressions */
+/*
+ * GCC statement expressions with non-expressions.
+ *
+ * https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
+ */
+
 struct cpu_info {
 	int bar;
 };
 
 int
-compound_expression_with_decl_and_stmt(void)
+statement_expr_with_decl_and_stmt(void)
 {
 	return ({
 	    struct cpu_info *ci;
@@ -17,7 +22,7 @@ compound_expression_with_decl_and_stmt(v
 }
 
 int
-compound_expression_with_only_stmt(void)
+statement_expr_with_only_stmt(void)
 {
 	struct cpu_info ci = { 0 };
 	return ({
@@ -26,3 +31,19 @@ compound_expression_with_only_stmt(void)
 		ci;
 	}).bar;
 }
+
+/*
+ * Since main1.c 1.58 from 2021-12-17 and before tree.c 1.404 from
+ * 2022-02-26, lint ran into an assertion failure due to a use-after-free.
+ * When typeok checked the operand types of the '=', the left node and the
+ * right node overlapped by 16 out of their 40 bytes on x86_64.
+ */
+void
+statement_expr_with_loop(unsigned u)
+{
+	u = ({
+		do {
+		} while (0);
+		u;
+	});
+}

Index: src/tests/usr.bin/xlint/lint1/t_integration.sh
diff -u src/tests/usr.bin/xlint/lint1/t_integration.sh:1.74 src/tests/usr.bin/xlint/lint1/t_integration.sh:1.75
--- src/tests/usr.bin/xlint/lint1/t_integration.sh:1.74	Sat Feb 26 16:43:20 2022
+++ src/tests/usr.bin/xlint/lint1/t_integration.sh	Sat Feb 26 20:36:11 2022
@@ -1,4 +1,4 @@
-# $NetBSD: t_integration.sh,v 1.74 2022/02/26 16:43:20 rillig Exp $
+# $NetBSD: t_integration.sh,v 1.75 2022/02/26 20:36:11 rillig Exp $
 #
 # Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -145,27 +145,6 @@ check_lint1()
 	fi
 }
 
-atf_test_case 'assertion_failures'
-assertion_failures_body()
-{
-	# seen in sys/external/bsd/drm2/include/linux/kref.h:73
-
-	cat <<'EOF' > input.c
-# 2 "input.c"
-void
-fn(unsigned int u)
-{
-	u = ({
-		do {} while (0);
-		u;
-	});
-}
-EOF
-
-	atf_check -s 'signal' -e 'match:lint: assertion ".*" failed' \
-	    "$lint1" -gS 'input.c' '/dev/null'
-}
-
 atf_init_test_cases()
 {
 	local src name
@@ -183,6 +162,4 @@ atf_init_test_cases()
 		}"
 		atf_add_test_case "$name"
 	done
-
-	atf_add_test_case 'assertion_failures'
 }

Index: src/usr.bin/xlint/lint1/cgram.y
diff -u src/usr.bin/xlint/lint1/cgram.y:1.380 src/usr.bin/xlint/lint1/cgram.y:1.381
--- src/usr.bin/xlint/lint1/cgram.y:1.380	Sat Feb 26 19:01:09 2022
+++ src/usr.bin/xlint/lint1/cgram.y	Sat Feb 26 20:36:11 2022
@@ -1,5 +1,5 @@
 %{
-/* $NetBSD: cgram.y,v 1.380 2022/02/26 19:01:09 rillig Exp $ */
+/* $NetBSD: cgram.y,v 1.381 2022/02/26 20:36:11 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: cgram.y,v 1.380 2022/02/26 19:01:09 rillig Exp $");
+__RCSID("$NetBSD: cgram.y,v 1.381 2022/02/26 20:36:11 rillig Exp $");
 #endif
 
 #include <limits.h>
@@ -517,8 +517,10 @@ postfix_expression:
 		$$ = build_name(*current_initsym(), false);
 		end_initialization();
 	  }
-	| T_LPAREN compound_statement_lbrace gcc_statement_expr_list {
-		do_statement_expr($3);
+	| T_LPAREN compound_statement_lbrace {
+		begin_statement_expr();
+	  } gcc_statement_expr_list {
+		do_statement_expr($4);
 	  } compound_statement_rbrace T_RPAREN {
 		$$ = end_statement_expr();
 	  }

Index: src/usr.bin/xlint/lint1/externs1.h
diff -u src/usr.bin/xlint/lint1/externs1.h:1.145 src/usr.bin/xlint/lint1/externs1.h:1.146
--- src/usr.bin/xlint/lint1/externs1.h:1.145	Sat Feb 26 19:01:09 2022
+++ src/usr.bin/xlint/lint1/externs1.h	Sat Feb 26 20:36:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: externs1.h,v 1.145 2022/02/26 19:01:09 rillig Exp $	*/
+/*	$NetBSD: externs1.h,v 1.146 2022/02/26 20:36:11 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -262,6 +262,7 @@ extern	bool	constant_addr(const tnode_t 
 extern	strg_t	*cat_strings(strg_t *, strg_t *);
 extern  unsigned int type_size_in_bits(const type_t *);
 
+void begin_statement_expr(void);
 void do_statement_expr(tnode_t *);
 tnode_t *end_statement_expr(void);
 

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.403 src/usr.bin/xlint/lint1/tree.c:1.404
--- src/usr.bin/xlint/lint1/tree.c:1.403	Sat Feb 26 19:01:09 2022
+++ src/usr.bin/xlint/lint1/tree.c	Sat Feb 26 20:36:11 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: tree.c,v 1.403 2022/02/26 19:01:09 rillig Exp $	*/
+/*	$NetBSD: tree.c,v 1.404 2022/02/26 20:36:11 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: tree.c,v 1.403 2022/02/26 19:01:09 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.404 2022/02/26 20:36:11 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -4539,13 +4539,30 @@ check_precedence_confusion(tnode_t *tn)
 	}
 }
 
+typedef struct stmt_expr {
+	struct memory_block *se_mem;
+	sym_t *se_sym;
+	struct stmt_expr *se_enclosing;
+} stmt_expr;
+
+static stmt_expr *stmt_exprs;
+
+void
+begin_statement_expr(void)
+{
+	stmt_expr *se = xmalloc(sizeof(*se));
+	se->se_mem = expr_save_memory();
+	se->se_sym = NULL;
+	se->se_enclosing = stmt_exprs;
+	stmt_exprs = se;
+}
+
 void
 do_statement_expr(tnode_t *tn)
 {
 	block_level--;
 	mem_block_level--;
-	/* Use the initialization code as temporary symbol storage. */
-	begin_initialization(mktempsym(dup_type(tn->tn_type)));
+	stmt_exprs->se_sym = mktempsym(dup_type(tn->tn_type));
 	mem_block_level++;
 	block_level++;
 	/* ({ }) is a GCC extension */
@@ -4556,7 +4573,11 @@ do_statement_expr(tnode_t *tn)
 tnode_t *
 end_statement_expr(void)
 {
-	tnode_t *tn = build_name(*current_initsym(), false);
-	end_initialization();
+	stmt_expr *se = stmt_exprs;
+	tnode_t *tn = build_name(se->se_sym, false);
+	expr_save_memory();	/* leak */
+	expr_restore_memory(se->se_mem);
+	stmt_exprs = se->se_enclosing;
+	free(se);
 	return tn;
 }

Reply via email to